Reputation: 1606
I would like to sandwich a vertical layout between two elements for large screens (example-2) – and for small screens, have the left-most and inner-top-most elements next to each other, and then everything else below it (example-3).
But I am trying to prevent having to write two different HTML structures, which is the only way I can currently achieve this. I wonder if I can do this with flexbox.
(function(){
const toggle_butt = document.querySelector('[name="mobile"]');
const root_el = document.querySelector('.root');
if (!toggle_butt || !root_el) {
return false;
}
toggle_butt.onchange = () => {
if (root_el.classList.contains('mobile')) {
root_el.classList.remove('mobile');
} else {
root_el.classList.add('mobile');
}
};
})()
.root {
max-width: 600px;
border: 1px dashed gray;
padding: 0.25rem;
}
.root.mobile {
max-width: 320px;
}
.controller {
margin-bottom: 0.5rem;
}
[class*="example-"] + [class*="example-"] {
margin-top: 1rem;
}
.d-flex {
display: flex;
flex-wrap: wrap;
}
.red, .yellow, .green, .blue {
min-width: 50px;
min-height: 40px;
}
.red {
background-color: tomato;
}
.yellow {
background-color: gold;
height: 40px;
}
.green {
background-color: limegreen;
height: 50px;
}
.blue {
background-color: cornflowerblue;
}
/* ----------- */
.example-1 .red {
flex: 0 0 20%;
}
.example-1 .yellow {
flex: 1 0 70%;
}
.example-1 .green {
flex: 0 0 100%;
}
.example-1 .blue {
flex: 0 0 100px;
}
.root.mobile .example-1 .blue {
flex: 1 0 100%;
}
/* ----------- */
.example-2 .red {
flex: 0 0 20%;
}
.example-2 .yellow,
.example-2 .green {}
.example-2 .blue {
flex: 0 0 100px;
}
.example-2 .cheat {
flex: 1 0 50%;
}
/* ----------- */
.example-3 .red {
flex: 0 0 20%;
}
.example-3 .yellow {
flex: 1 0 70%;
}
.example-3 .green,
.example-3 .blue {
flex: 1 0 100%;
}
.example-3 .cheat {
display: flex;
flex: 1 0 100%;
}
<div class="root">
<div class="controller">
<label>
<input type="checkbox" name="mobile" />
<span class="text">mobile</span>
</label>
</div>
<div class="example-1 d-flex">
<div class="red"></div>
<div class="yellow">Can flex do it?</div>
<div class="green"></div>
<div class="blue"></div>
</div>
<div class="example-2 d-flex">
<div class="red"></div>
<div class="cheat">
<div class="yellow">Goal: desktop</div>
<div class="green"></div>
</div>
<div class="blue"></div>
</div>
<div class="example-3 d-flex">
<div class="cheat">
<div class="red"></div>
<div class="yellow">Goal: mobile</div>
</div>
<div class="green"></div>
<div class="blue"></div>
</div>
</div>
It's not important for green to line up with the bottom edge of red and blue.
Red is an image and yellow is a headline; that is why I'm trying to do this.
StackOverflow questions I looked at (but they're not quite the same):
Upvotes: 0
Views: 267
Reputation: 22959
You can use Grid's grid-template-areas
property:
(function() {
const toggle_butt = document.querySelector('[name="mobile"]');
const root_el = document.querySelector('section');
if (!toggle_butt || !root_el) {
return false;
}
toggle_butt.onchange = () => {
if (root_el.classList.contains('mobile')) {
root_el.classList.remove('mobile');
} else {
root_el.classList.add('mobile');
}
};
})()
div {
min-height: 40px;
}
.red {
background: red;
}
.yellow {
background: yellow;
}
.green {
background: green;
}
.blue {
background: blue;
}
section {
display: grid;
grid-template-columns: 2fr 5fr 100px;
grid-template-areas: "r y b" "r g b"
}
.red {
grid-area: r;
}
.yellow {
grid-area: y;
}
.blue {
grid-area: b;
}
.green {
grid-area: g;
}
section.mobile {
grid-template-areas: "r y y" "g g g" "b b b"
}
<label>
<input type="checkbox" name="mobile" />
<span class="text">mobile</span>
</label>
<section>
<div class="red"></div>
<div class="yellow"></div>
<div class="green"></div>
<div class="blue"></div>
</section>
Upvotes: 1