Here a coarse scaling of what I'm trying to do :
As you can see, I want to make several "organizations" of my three blocks :
On Large screens (and larger), I want them to be next to each other
On Medium screens, I want the first and the third block on the same row, and the second bloc on another row
On Small screens, I want them each to be one below the other
So, the problem appears on medium screens, the third block needs to be before the second block.
To solve it, I put the third block twice :
One between the first block and the second block (with the class rule "show-for-medium-only")
The other one after the second block (with the class rule "hide-for-medium-only")
Which gives me this html (you can see it in action here) :
<div class="row">
<div class="small-12 medium-4 large-3 columns">
<div class="panel">
1
</div>
</div>
<div class="show-for-medium-only medium-8 columns">
<div class="panel">
3
</div>
</div>
<div class="small-12 medium-12 large-5 columns">
<div class="panel">
2
</div>
</div>
<div class="hide-for-medium-only small-12 large-4 columns">
<div class="panel">
3
</div>
</div>
</div>
So my question is : Is there any ways to do it without duplicating the third block ? (Without using JavaScript, preferably with native Foundation rules)
You can use source-ordering or removing elements from the document flow and ordering them in layers with css and some html boilerplate:
http://jsfiddle.net/uw8U8/
html:
<div class="wrapper">
<div class="row layer-1">
<div class="small-12 medium-4 large-3 columns">
<div class="panel first">
1
</div>
</div>
<div class="small-12 medium-8 large-4 large-offset-5 third-column columns">
<div class="panel dummy"></div>
<div class="panel dummy"></div>
<div class="panel third">
3
</div>
</div>
</div>
<div class="row layer-2">
<div class=" medium-12 large-5 large-offset-3 columns">
<div class="panel second">
2
</div>
</div>
</div>
</div>
and app.scss
#import "settings";
#import "foundation";
.wrapper{
position: relative;
margin: auto;
max-width: $row-width;
}
.panel{
text-align: center;
height: 1.5em;
font-size: 1000%;
color: white;
}
.first{
background-color:#e64433;
}
.second{
background-color:#09afb9;
}
.third{
background-color:#ed9a24;
}
#media #{$large-up} {
.layer-1, .layer-2{
position: absolute;
}
}
.dummy{
display: none;
}
#media #{$small-only} {
.third-column{
position: absolute;
}
.dummy{
display: block;
visibility: hidden;
}
}
or css output for the default Foundation 5 setting:
.wrapper {
position: relative;
margin: auto;
max-width: 62.5rem;
}
/* line 11, ../scss/app.scss */
.panel {
text-align: center;
height: 1.5em;
font-size: 1000%;
color: white;
}
/* line 18, ../scss/app.scss */
.first {
background-color: #e64433;
}
/* line 21, ../scss/app.scss */
.second {
background-color: #09afb9;
}
/* line 24, ../scss/app.scss */
.third {
background-color: #ed9a24;
}
#media only screen and (min-width: 64.063em) {
/* line 30, ../scss/app.scss */
.layer-1, .layer-2 {
position: absolute;
}
}
/* line 35, ../scss/app.scss */
.dummy {
display: none;
}
#media only screen and (max-width: 40em) {
/* line 39, ../scss/app.scss */
.third-column {
position: absolute;
}
/* line 42, ../scss/app.scss */
.dummy {
display: block;
visibility: hidden;
}
}
Not really a Foundation oriented answer, but with display: grid; being widely supported, this solution should work with any CSS framework and will make the HTML much cleaner and the CSS much more flexible 😀 (by doing this, you also keep the styling out of the HTML document, which is a good practice and better for maintainability 😉)
The idea is to re-create a grid of 12 columns using :
display: grid;
grid-template-columns: repeat(12, 1fr);
And then span our panels on the corresponding number of columns using :
grid-column: span {{ number of column }};
Which gives us this :
html, body {
margin: 0;
padding: 0;
}
.grid {
display: grid;
grid-template-columns: repeat(12, 1fr); /* 1fr = 1 column */
grid-gap: 20px; /* gutter beetween each column and row */
margin: 20px;
}
.panel {
height: 180px;
line-height: 180px;
text-align: center;
font-size: 50px;
font-family: Impact, sans-serif;
color: #fff;
}
/* large screen */
.panel:nth-child(1) {
grid-column: span 3; /* 3 columns */
background-color: #e64433;
}
.panel:nth-child(2) {
grid-column: span 5; /* 5 columns */
background-color: #09afb9;
}
.panel:nth-child(3) {
grid-column: span 4; /* 4 columns */
background-color: #ed9a24;
}
/* medium screen */
#media (max-width: 1000px) {
.panel:nth-child(1) {
order: 1;
grid-column: span 4;
}
.panel:nth-child(2) {
order: 3;
grid-column: span 12;
}
.panel:nth-child(3) {
order: 2;
grid-column: span 8;
}
}
/* small screen */
#media (max-width: 600px) {
.panel:nth-child(1) {
order: 1;
grid-column: span 12;
}
.panel:nth-child(2) {
order: 2;
grid-column: span 12;
}
.panel:nth-child(3) {
order: 3;
grid-column: span 12;
}
}
<div class="grid">
<div class="panel">
1
</div>
<div class="panel">
2
</div>
<div class="panel">
3
</div>
</div>
You may also consider grid-template and grid-area which is a bit harder to understand at first sight, but may allow you to be more creative depending on your needs
Here is the result :
html, body {
margin: 0;
padding: 0;
}
.grid {
display: grid;
grid-template: "pannel1 pannel2 pannel3" auto / 3fr 5fr 4fr;
grid-gap: 20px;
margin: 20px;
}
.panel {
height: 180px;
line-height: 180px;
text-align: center;
font-size: 50px;
font-family: Impact, sans-serif;
color: #fff;
}
/* large screen */
.panel:nth-child(1) {
grid-area: pannel1;
background-color: #e64433;
}
.panel:nth-child(2) {
grid-area: pannel2;
background-color: #09afb9;
}
.panel:nth-child(3) {
grid-area: pannel3;
background-color: #ed9a24;
}
/* medium screen */
#media (max-width: 1000px) {
.grid {
grid-template:
"pannel1 pannel3" auto
"pannel2 pannel2" auto / 1fr 2fr;
}
}
/* small screen */
#media (max-width: 600px) {
.grid {
grid-template:
"pannel1" auto
"pannel2" auto
"pannel3" auto / 1fr;
}
}
<div class="grid">
<div class="panel">
1
</div>
<div class="panel">
2
</div>
<div class="panel">
3
</div>
</div>
Beware that the above solutions preserve the original document flow, which means, that if you want to "Tab" through the focusable elements of the page, it will always go to the second panel before the third, even though you'd expect to go to the third panel before the second on medium screens.
If it is a problem for you, you'll need either JS to automatically update tabindex properties on your pannels, or to re-order element in the HTML DOM itself, and if using JS is not a solution for you, then the code example in the original post is the only way to go I guess.
But remember that rearranging items in the DOM depending on the screen's size may not always be a good idea for accessibility :
Rearranging grid items visually does not affect the default traversal order of sequential navigation modes (such as cycling through links).
[CSS Grid Layout and Accessibility]
Related
I have started web dev not that long ago, and today I really tried to understand the basics of css and html, and I've got almost everything to work correctly. But I'm facing a problem that I can't seem to be able to solve by myself.
So here I am. I'm trying to replicate this design I did on figma, as a challenge for myself, and as a huge fan of Family Guy :
See the image here
So I started by learning how to create a css grid (I thought it was going to be usefull for each part of the page), then how to create a side bar and all of that. But there I am stuck :
My whole page is cranked into a tiny part :
This
For further investigation, here's the grid in inspect mode :
This
So how can I make it take the whole page like it should :
Here's my html and css
HTML
<!DOCTYPE html>
<head>
<title>FamilyGuy</title>
<link rel="stylesheet" type="text/css" href="./assets/css/styles.css">
</head>
<body>
<div class="container">
<div class="navbar">
</div>
<div class="card-1">
<div class="card-image-container">
<img class="card-image" src="./assets/img/Family_Guy_Season1.png">
</div>
<div class="card-title-container">
<h3 class="card-title">Episode 1</h3>
</div>
</div>
<div class="card-2">
<div class="card-image-container">
<img class="card-image" src="./assets/img/Family_Guy_Season1.png">
</div>
<div class="card-title-container">
<h3 class="card-title">Episode 2</h3>
</div>
</div>
</body>
</html>
CSS
html {
display: block;
margin: 0;
padding: 0;
}
body {
background: #1E1E1E;
font-family: 'Inter', sans-serif;
border: 0;
margin: 0;
padding: 0;
}
.container {
display: grid;
max-width: 1920px;
max-height: 1080px;
grid-template-columns: [first] 18.23% [second] 2.6% [third] auto [fourth] 2.6% [fifth] auto [sixth] 2.6% [seventh] auto [eighth] 2.6% [ninth] auto [tenth] 2.6% [eleventh] 42.19%;
grid-template-rows: [first] 2.78% [second] 2.78% [third] 5.28% [fourth] 13.89% [five] 3.06% [sixth] 19.44% [seventh] 2.6% [ninth] 19.44% [tenth] 2.6% [eleventh] 19.44% [twelveth] 2.6%;
}
div.navbar {
background: #2F3136;
max-width: 350px;
max-height: 1080px;
grid-column-start: first;
grid-column-end: span second;
grid-row-start: first;
grid-row-end: span twelveth;
}
div.card-1 {
position: inherit;
background: #2F3136;
max-width: 140px;
max-height: 210px;
grid-column-start: third;
grid-column-end: span fourth;
grid-row-start: sixth;
grid-row-end: seventh;
border-radius: 7.14%;
}
div.card-2 {
position: inherit;
background: #2F3136;
max-width: 140px;
max-height: 210px;
grid-column-start: fifth;
grid-column-end: span sixth;
grid-row-start: sixth;
grid-row-end: seventh;
border-radius: 7.14%;
}
div.card-image-container {
display: flex;
justify-content: center;
position: relative;
max-width: 120px;
max-height: 158.68px;
border-radius: 7.14%;
padding: 7.14%;
border-radius: 7.14%;
width: 85.71%;
height: 75.56%;
}
img.card-image {
display: flex;
border-radius: 7.14%;
justify-content: center;
}
div.card-title-container {
display: flex;
justify-content: center;
align-items: center;
position: relative;
max-width: 140px;
max-height: 41px;
}
h3.card-title {
display: flex;
margin-bottom: 0;
margin-top: .2em;
margin-left: 0;
margin-right: 0;
}
h3 {
font-size: 1rem;
color: #FFFFFF;
font-weight: 500;
}
Please keep in mind that I just started static web dev recently, and that there may be a lot of errors in my code. I already apologize for the possible big noob error I could have done. This is actually my first time really trying to do something without any template or base code, so yeah, I'm kinda going blindfolded into this challenge. Already thanks for the help !
As stated. I've tried to replicate my figma design, but my body/html won't spread all the way on the page.
UPDATE : looks like using :
<div class="container" style="height: 852px">
In the HTML, fixed my problem. Alhough, I'm not entirely satisfied of this, as it creates a scroll bar on the right. Which I'm not particularly a fan of. If any of you has ideas, I would gladly appreciate it.
There are two major problems with your code, apart from your issue:
The page is constructed as one large grid. Espescially CSS Grid can be very intimidating creating such grid, where Flexbox Layout will probably feel more intuitive.
From your image it is clear that you have designed a main page with three main sub panels, each with its own distinct function. Tools, Navigation & Image Grid and Preview.
Each sub panel can be divided into several child panels and in some cases ever deeper nested panels.
Fixed units like px are your enemy, particularly when you want to design a responsive web page that can fit on various devices. Percentages based on a fixed value, while relative, will still eventually result in fixed values, e.g. 10% of 1920px will always be 192px. This will likely lead to cascading element size and positioning issues.
Instead of helping you with an issue in code you most likely will want to change one way or another, I took the liberty of creating a responsive base framework you can extend and modify to your needs:
I divided your design into the nested panels mentioned before and removed all fixed units, except for a few in the media queries.
Introduced a few Flexbox Layout shortcut (one letter) attribute selectors for easy 'on-the-fly' flexbox use.
Element font sizes defined as parent dependent (em unit).
Element sizes and spacing as root dependent (rem unit).
Comments are in the CSS where applicable.
Downloadable version of the code at Codepen.
There is still a lot to do, I didn't create the entire page for you, but maybe this will give you a head start...
Snippet
/* * { outline: 1px dashed white }/* for debugging only */
/********************************/
/* some convenient global rules */
/********************************/
* { box-sizing: border-box }
html, body { width: 100%; max-width: 100% }
body { min-height: 100vh; margin: 0 }
/* Linear equation y=mx+b using points p1(320,12) p2(1280,18) */
body { font-size: calc(0.625vmin + 0.625rem) } /* responsive page font */
img {
display: block; /* removes whitespace below image */
object-fit: cover; /* fill, but clip when lack of room */
width: 100%; /* width is leading */
height: 100%;
}
iframe { border: none; max-width: 100% }
/* this and thats */
.icon { display: inline-grid; place-items: center; padding: 0.25rem }
.big { font-size: 1.75em; font-weight: bolder }
.small { font-size: 0.75em }
/* Easy flexbox shorcuts for on-the-fly use */
[F] { display: flex; flex-wrap: wrap }
[R] { flex-direction: row } /* flexbox default */
[C] { flex-direction: column }
[N] { flex-wrap: nowrap } /* Flexbox default */
[F] > * { flex: 1 } /* allow flexbox kids to grow */
body {
background-color: #1e1e1e; color: White;
font-family: 'Inter', sans-serif;
line-height: 1.5;
}
header, footer, nav {
display: flex; align-items: center;
width: 100%;
padding: 0.5rem 0;
font-weight: bold;
}
header { font-size: 1.5rem; justify-content: center }
footer { font-size: 0.8rem; justify-content: end }
/***************/
/* end globals */
/***************/
/**********************/
/* Main app container */
/**********************/
.main {
display: flex; flex-wrap: wrap;
width: 100%; min-height: 100vh; /* fill parent */
background-color: #2f3136;
}
/******************/
/* All sub panels */
/******************/
.sub {
/* Flexbox column (of rows) container */
display: flex; flex-flow: column wrap;
gap: 1rem; /* generic gap between various content panels */
/* this will make a panel fit snuggly in a 320px or 360px device */
min-width: min(18rem, 100%); /* = 288/16 or 100% */
padding: 0.5rem 2rem;
}
.sub footer { margin-top: auto } /* move to bottom */
/* Footers are here to show height of panels */
/* panel spacing ratio 1:2:2 (comparable to grid 'fr' unit) */
/* when available and respecting .sub min-width */
.sub.tools { flex: 1 } /* allow to grow, where */
.sub.episodes { flex: 2 } /* flex-shrink = 1 and */
.sub.preview { flex: 2 } /* flex-basis = 0% */
/*******************/
/* Sub tools panel */
/*******************/
.search label { width: 100%; }
.search .icon { font-size: 1.5em }
.search input { font-size: 1em; width: calc(100% - 1.5em - 0.5rem) }
/* 100% minus icon size minus L/R icon padding */
/**********************/
/* Sub episodes panel */
/**********************/
.sub.episodes {
/* Define custom property for numer of image columns */
--img-columns: 2; /* mobile first: 2 columns only */
/* Overridden by Media Queries */
background-color: #36393f;
}
.navigation { font-size: 1.75em }
/* Default for small devices < 720px */
.episode-grid {
/* Use column value set by Media Queries */
display: grid; grid-template-columns: repeat(var(--img-columns), 1fr);
gap: 0.5rem;
}
/* Media queries for gradually bigger devices, change as required */
/* Common use */
/*#media screen and (min-width: 721px) { .episode-grid { grid-template-columns: repeat(3, 1fr) } } /* > 720px */
/*#media screen and (min-width: 1081px) { .episode-grid { grid-template-columns: repeat(4, 1fr) } } /* > 1080px */
/*#media screen and (min-width: 1367px) { .episode-grid { grid-template-columns: repeat(5, 1fr) } } /* > 1366px */
/*#media screen and (min-width: 1921px) { .episode-grid { grid-template-columns: repeat(7, 1fr) } } /* > 1920px */
/* Custom property use */
/* Custom properties defined at parent element level, modified and used at element child level */
#media screen and (min-width: 721px) { .episode-grid { --img-columns: 3 } } /* > 720px */
#media screen and (min-width: 1081px) { .episode-grid { --img-columns: 4 } } /* > 1080px */
#media screen and (min-width: 1367px) { .episode-grid { --img-columns: 5 } } /* > 1366px */
#media screen and (min-width: 1921px) { .episode-grid { --img-columns: 7 } } /* > 1920px */
.card .small { text-align: center }
/*********************/
/* Sub preview panel */
/*********************/
.sub.preview .content { gap: 1rem }
.thumblist, .settings {
gap: 0.25rem;
padding: 1rem;
background-color: #36393f;
border-radius: 0.5rem;
}
.thumb {
padding: 0.5rem;
background-color: #2f3136;
}
.card,.thumb { border-radius: 0.5rem; padding: 0.5rem; background-color: #2f3136 }
:is(.card,.thumb) img { border-radius: 0.75rem }
<!-- Main app container -->
<div class="main">
<!-- Tools sub panel -->
<div class="sub tools">
<header>
<div class="logo">
<img src="https://i.imgur.com/gEQ9EK6.png">
</div>
</header>
<div class="search" F C>
<div class="bar">
<label><input placeholder="Search"><span class="icon">ⓘ</span></label>
</div>
<div class="results">
<div class="list" F C>
<div>result one</div>
<div>result two</div>
<div>result three</div>
<div>result four</div>
<div>result five</div>
<div>result six</div>
</div>
<div class="dots">...</div>
</div>
</div>
<div class="more-tools" F C>
<div class="tool one" >tool one</div>
<div class="tool two" >tool two</div>
<div class="tool three">tool three</div>
</div>
<footer>tools</footer>
</div>
<!-- Episodes sub panel -->
<div class="sub episodes">
<header></header>
<div class="page-control" F C>
<nav class="navigation" F>
<div class="option"><span class="icon">ⓘ</span><span class="text">text</span></div>
<div class="option"><span class="icon">ⓘ</span><span class="text">text</span></div>
<div class="option"><span class="icon">ⓘ</span><span class="text">text</span></div>
<div class="option"><span class="icon">ⓘ</span><span class="text">text</span></div>
</nav>
<div class="title">
<div class="big">FamilyGuy.Com</div>
<p class="small">Lorem ipsum dolor sit amet, eos ad wisi eius deserunt, cu iusto nonumes volumus usu, ne aeque aperiam saperet pro. Cu eum laudem sanctus, apeirian torquatos assentior mea ea, eos ut tantas altera sadipscing. Nam splendide voluptatum ad, integre quaeque definitiones mea et.</p>
</div>
</div>
<div class="episode-grid">
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=1">
<div class="small">byline</div>
</div>
</div>
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=2">
<div class="small">byline</div>
</div>
</div>
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=3">
<div class="small">byline</div>
</div>
</div>
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=4">
<div class="small">byline</div>
</div>
</div>
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=5">
<div class="small">byline</div>
</div>
</div>
</div>
<footer>episodes</footer>
</div>
<!-- Movie preview sub panel -->
<div class="sub preview">
<header>Live preview</header>
<div class="content" F C>
<div class="movie">
<iframe src="https://www.youtube.com/embed/N-nJ3EMueyE"
title="Family Guy - Fight with the hologram (Season 21 Episode 6)"
frameborder="0" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>
</div>
<div>
<div class="episode-selector">Episode selector</div>
</div>
<div class="highlights" F C>
<div>Highlights</div>
<div class="thumblist" F R>
<div class="thumb"><img src="https://picsum.photos/200/112?random=6"></div>
<div class="thumb"><img src="https://picsum.photos/200/112?random=7"></div>
<div class="thumb"><img src="https://picsum.photos/200/112?random=8"></div>
<div class="thumb"><img src="https://picsum.photos/200/112?random=9"></div>
</div>
</div>
<div class="settings" F>
<div class="subtitle" F C>
<p>Available Subtitles</p>
<label class="small">English <input type="checkbox"></label>
<label class="small">French <input type="checkbox"></label>
<label class="small">Spanish <input type="checkbox"></label>
</div>
<div class="audio" F C>
<p>Available Audio tracks</p>
<label class="small">English <input type="checkbox"></label>
<label class="small">French <input type="checkbox"></label>
<label class="small">Spanish <input type="checkbox"></label>
</div>
</div>
</div>
<footer>preview</footer>
</div>
</div>
This question already has answers here:
Make a div span two rows in a grid
(2 answers)
Closed 3 years ago.
I am trying to create a layout which allows me change the order of elements between mobile and desktop as demonstrated by the diagram bellow:
I have ordered them in the DOM within a single container in the order as they are numbered. I'm trying to get the second item to display to the left as shown. I tried with flex but couldn't get it right. I also tried floating the second div to the left and the rest to the right, but this is messy, especially if the 4th element in right column overlaps the 3rd.
Can somebody help me with this?
Thanks
This might be better suited to CSS Grid Layout and media queries.
.container {
display: grid;
grid-template-columns: repeat(1, 1fr);
}
#media(min-width: 375px) {
.container {
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(2, 1fr);
}
.child2 {
grid-row-start: 1;
grid-row-end: 4;
}
}
<div class="container">
<div>1</div>
<div class="child2">2</div>
<div>3</div>
<div>4</div>
</div>
Example using CSS grid:
section {
display: grid;
grid-template-areas: "block1" "block2" "block3" "block4"
}
.block-1 {
grid-area: block1;
background-color: red;
}
.block-2 {
grid-area: block2;
background-color: blue;
}
.block-3 {
grid-area: block3;
background-color: green;
}
.block-4 {
grid-area: block4;
background-color: yellow;
}
#media screen and (min-width: 767px) {
section {
grid-template-areas: "block2 block1" "block2 block3" "block2 block4"
}
}
<section>
<div class="block-1">
Block 1
</div>
<div class="block-2">
Block 2
</div>
<div class="block-3">
Block 3
</div>
<div class="block-4">
Block 4
</div>
</section>
try this
.container {
display: flex;
flex-wrap: wrap;
position: relative;
}
.container .inner-container1 {
flex-grow: 2;
}
.container .inner-container2 {
flex-grow: 1;
}
.box {
flex-grow: 1;
}
.diff {
position: absolute;
width: 50%;
background-color: red;
left: 0px;
top: 0px;
height: 100%;
}
/* set your desired max-width */
#media screen and (max-width: 500px) {
.diff {
position: initial;
width: initial;
}
.container .inner-container1 {
display: none;
}
}
<div class="container">
<div class="inner-container1">
</div>
<div class="inner-container2">
<div class="box">1</div>
<div class="box diff">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
I want to arrange 3 divs, according to the screen width as follows:
For screen-width of < 500px arrangement should be as follows :
For screen-width of > 500px arrangement should be as follows :
I have tried achieving this in screen size of > 500px but i don't know how to use the same code to achieve arrangement for <500px.
My doubt is, can I use the same piece of code to get both the arrangements or is there any other approach ? Can flexbox be used to solve the issue?
Here is the snippet:
.container {
display: flex;
}
.divA {
flex: 0 0 40%;
align-self: flex-end;
}
.container-2 {
display: flex;
flex: 0 0 60%;
flex-direction: column;
}
<div class="container">
<div class="divA">
A
</div>
<div class="container-2">
<div class="divB">
B
</div>
<div class="divC">
C
</div>
</div>
</div>
edit
after seeing your question update , mediaquerie, flex, order , and a pseudo to create that empty gap , should be enough. Still with each 3 boxes direct child of .container.
run the code snippet in fullpage mode and resize your browser , break point set at 700px for the demo.
* {
box-sizing: border-box;
margin: 0;
}
.container {
display: flex;
flex-wrap: wrap;
}
.divA {
background: lightgreen;
}
.divB {
background: lightblue;
}
.divC {
background: rgb(255, 255, 0);
}
.container>div,
.container:before {
flex: 1;
min-width: 40%;
padding: 1em 0;
text-align: center;
}
#media (min-width: 700px) {
/* upadte here the px value where you swhitch to happen . 500px */
.divA,
.divC {
order: 1;
flex: 0 1 40%;
}
.container .divB,
.container .divC {
flex: 0 1 60%;
}
.container:before {
content: "";
flex: 0 1 40%;
}
}
<div class="container">
<div class="divA">
A
</div>
<div class="divB">
B
</div>
<div class="divC">
C
</div>
</div>
original answer left here for infos
you may switch from a flex layout to a table or grid layout with each elelemnts as sibblings, no need of extra markup here.
exemple : flex/table , it would be for browser still having issues with grid
.container {
display: flex;
flex-wrap: wrap;
}
.container>div {
flex: 1;
border: solid;
min-width: 40%;
}
/* set here the width where you want switching layout */
#media screen and (max-width: 600px) {
.container {
display: table;
width: 100%;
table-layout: fixed;
;
}
.divA {
display: table-cell;
width: 50%;
}
<div class="container">
<div class="divA">
A
</div>
<div class="divB">
B
</div>
<div class="divC">
C
</div>
</div>
or grid (mind version of IE which supports grid partially and requires to set grid-row/grid-column or grid-area for each children)
.container {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.container>div {
border: solid;
}
.divC {
grid-row: 2;
grid-column:1 / span 2;
}
/* set here the width where you want switching layout */
#media screen and (max-width: 600px) {
.divC {
grid-row: 1 / span 2;
grid-column: 1;
}
<div class="container">
<div class="divA">
A
</div>
<div class="divB">
B
</div>
<div class="divC">
C
</div>
</div>
How:
This can be achieved with css grid
If you are open to grid solution, You need to change your html structure a bit. With flex that's impossible.
Solution:
Here is what I would do:
.container {
display: grid;
grid-template-columns: 50% 50%;
grid-template-rows: 200px 200px;
grid-gap: 0;
}
.divA {
background-color: lightgreen;
}
.divB {
background-color: lightblue;
}
.divC {
grid-column: 1 / span 2;
background-color: yellow;
}
#media screen and (min-width: 500px) {
.divA {
grid-column: 2 / 1;
grid-row: 2 / 2
}
.divB {
grid-column: 2 / 2;
grid-row: 1 / 1;
}
.divC {
grid-column: 2 / 2;
grid-row: 2 / 2;
}
}
<div class="container">
<div class="divA">
A
</div>
<div class="divB">
B
</div>
<div class="divC">
C
</div>
</div>
Explanation:
grid-template-columns lets you define the column widths of your
grid elements, and same does the grid-template-rows for rows
heights.
For each grid element, you can specify how many elements they should
span ( such as table cell can span columns or rows ) with
grid-column. Learn more
here or google
this property. Your divC has spanned 2 elements in a column.
Now for your responsiveness, write a media query to define your
styles for screen-width more than 500px, and reset your .divCs
grid-column and grid-row and add the same for your .divA. (Since this element now spans 2 elements in a row)
I'm trying to build myself a flexbox with the following design:
My html looks like this (and I would like to NOT change this):
<div class="wrapper">
<div class="page-header">Heading</div>
<h3 class="right_1">right_1</h3>
<div class="right_2">right_2</div>
<div class="left">form element</div>
<h3 class="right_3">right_3</h3>
<div class="right_4">right_4</div>
</div>
This is the standard layout of the joomla contact page. I want to change the design though without altering html/php code.
Is that possible using flexbox?
And can I use #media queries to make right_1 - right_4 to move under left on mobile view (< 800px or example)?
I myself cannot get it to work, I always end up with right_1 - right_4 next to each other instead of them stacking to the total height of the left portion.
The layout you want cannot be achieved with flexbox. The reasons are explained here:
Is it possible for flex items to align tightly to the items above them?
However, the layout is relatively simple with CSS Grid.
There are, in fact, multiple methods for building the layout with Grid. I'll use the grid-template-areas property, which allows you to lay out your elements using ASCII art.
.wrapper {
display: grid;
height: 100vh;
grid-template-columns: 1fr 1fr;
grid-template-areas:
" heading heading "
" left_ right1 "
" left_ right2 "
" left_ right3 "
" left_ right4 "
}
.page-header { grid-area: heading; }
.right_1 { grid-area: right1; }
.right_2 { grid-area: right2; }
.right_3 { grid-area: right3; }
.right_4 { grid-area: right4; }
.left { grid-area: left_; } /* "left" is a pre-defined CSS keyword,
so it may not work */
#media ( max-width: 800px ) {
.wrapper {
grid-template-columns: 1fr;
grid-template-areas:
" heading "
" left_ "
" right1 "
" right2 "
" right3 "
" right4 "
}
}
/* non-essential decorative styles */
.page-header { background-color: red; }
.right_1 { background-color: chartreuse; }
.right_2 { background-color: aqua; }
.right_3 { background-color: skyblue; }
.right_4 { background-color: black; color: white; }
.left { background-color: cornsilk; }
body { margin: 0; }
.wrapper > * {
font-weight: bold;
font-size: 1.5em;
border: 1px solid black;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
<div class="wrapper">
<div class="page-header">Heading</div>
<h3 class="right_1">right_1</h3>
<div class="right_2">right_2</div>
<div class="left">form element</div>
<h3 class="right_3">right_3</h3>
<div class="right_4">right_4</div>
</div>
jsFiddle demo
In essence, here's how it works:
We establish a block-level grid with display: grid.
With grid-template-columns: 1fr 1fr we are telling the grid to create two columns. The fr unit tells the container to consume available space. It's similar to flexbox's flex-grow property. So both columns will share the full width of the container.
The grid-template-areas property allows you to lay out named grid areas (that you have defined) to create a visual representation of your layout using ASCII art.
In the media query for smaller screens, we remove one column and re-order the grid areas.
Browser Support for CSS Grid
Chrome - full support as of March 8, 2017 (version 57)
Firefox - full support as of March 6, 2017 (version 52)
Safari - full support as of March 26, 2017 (version 10.1)
Edge - full support as of October 16, 2017 (version 16)
IE11 - no support for current spec; supports obsolete version
Here's the complete picture: http://caniuse.com/#search=grid
Here is one way to solve that, based on the existing markup and CSS Flexbox.
The left needs to be absolute positioned for desktop view and the page-header need a fixed height.
If you don't want to set a fixed height, you'll need a script that takes care of the height calculation
html, body {
margin: 0;
}
.wrapper {
position: relative;
display: flex;
flex-direction: column;
min-height: 100vh;
}
.wrapper * {
padding: 0 10px;
margin: 0;
border: 1px solid black;
box-sizing: border-box;
}
.page-header {
height: 70px;
width: 100%;
background: red;
}
.right_1, .right_2, .right_3, .right_4 {
flex: 1;
width: 50%;
margin-left: 50%;
background: lightblue;
}
.left {
position: absolute;
left: 0;
top: 70px;
width: 50%;
min-height: calc(100vh - 70px);
background: yellow;
}
#media only screen and (orientation: portrait) {
.wrapper * {
width: 100%;
margin: 0;
}
.left {
position: static;
flex: 1;
min-height: auto;
order: -1
}
.page-header {
order: -2;
}
}
<div class="wrapper">
<div class="page-header">Heading</div>
<h3 class="right_1">right_1</h3>
<div class="right_2">right_2</div>
<div class="left">form element</div>
<h3 class="right_3">right_3</h3>
<div class="right_4">right_4</div>
</div>
Probably the easiest way to change the order of div elements, you can use Jquery for this purpose. For example:
$("#element1").before($("#element2"));
Eventually:
CSS:
#blocks {
display: box;
box-orient: vertical;
}
#b1 {
box-ordinal-group: 2;
}
#b2 {
box-ordinal-group: 3;
}
HTML:
<div id="blocks">
<div id="b1">Block 1</div>
<div id="b2">Block 2</div>
<div id="b3">Block 3</div>
</div>
It should work.
The result I'm looking for is one big block on the left, and then four small blocks on the right, and everything aligns.
I managed to do this in this fiddle but my solution has a couple of problems:
- it's not very clean in terms of code
- it's not responsive
HTML:
<div class="wrapper">
<div class="box big">ONE</div>
<div class="med-wrapper">
<div class="row-1">
<div class="box medium">TWO</div>
<div class="box medium">THREE</div>
</div>
<div class="row-2">
<div class="box medium">FOUR</div>
<div class="box medium">FIVE</div>
</div>
</div>
</div>
CSS:
.wrapper {
display: flex;
flex-direction: row;
flex-flow: row wrap;
justify-content: space-around;
height: 200px;
}
/* #media screen and (max-width: 768px) {
flex-direction: column
} */
.box {
background: #09f;
color: white;
padding: 1em;
margin: 5px;
text-align: center;
}
.big {
flex: 5;
}
.medium {
flex: 5;
height: 100px;
}
.med-wrapper {
display: flex;
}
Also, you might notice that I have set the flex on both .big and .medium to 5, because I want the total width of the big box and the total width of two medium boxes to be equal, but it didn't work.
Is there a better way to do this?
It's tricky to have everything to align without getting into a lot of constraints, but using flexbox wrapping in the column direction on the right part could work.
Here's a quick version that uses a flex-flow: column wrap on the right part (.med-wrapper) and gets rid of the wrapper element on the two column wrappers inside it -
<div class="wrapper">
<div class="box big">
ONE
</div>
<div class="med-wrapper">
<div class="box medium">TWO</div>
<div class="box medium">THREE</div>
<div class="box medium">FOUR</div>
<div class="box medium">FIVE</div>
</div><!-- /.med-wrapper -->
</div><!-- /.wrapper -->
...and then the CSS:
body {
font-family: 'calibri', sans-serif;
margin: 0;
}
.wrapper {
display: flex;
justify-content: space-around;
height: 200px;
}
.box {
background: #09f;
color: white;
padding: 1em;
margin: 0 5px;
text-align: center;
box-sizing: border-box;
}
.big {
flex: 1;
height: 100%;
}
.med-wrapper {
flex: 1;
display: flex;
height: 100%;
flex-flow: column wrap;
justify-content: space-between;
overflow: auto;
}
.medium {
/* exact sizing for the medium boxes (i.e. get it from main sizing.) */
flex: 0 0 auto;
/* adjust for margins: */
width: calc(50% - 10px);
height: calc(50% - 5px);
}
/* some theoretical adjustments for smaller screens */
#media screen and (max-width: 768px) {
/* switch the wrapper to column dir, and remove fixed height. */
.wrapper {
flex-direction: column;
height: auto;
}
/* just a min height for demo purposes. */
.big {
min-height: 200px;
}
/* Now we need to re-set a height on this one, if we
want to keep the 2x2 square thing. */
.med-wrapper {
margin-top: 10px;
height: 200px;
}
}
Live demo at http://jsbin.com/kasez/5/edit
I've used calc()for the size calculations to counter margins, but hey, if you're already depending on flexbox, you probably need a fallback anyway. :-)
It should work with just the one explicit height on the .wrapper element, but the rest of the items should adjust accordingly - the downside is that overflow handling gets hard.
This is, incidentally, the type of "2D" situation (vs flexbox's 1D) that Grid Layout is meant to help with, but it'll be a while before that is a viable option.