How to achieve specific css flexbox layout with multiple columns of different row items [duplicate] - css

This question already has answers here:
Make a div span two rows in a grid
(2 answers)
Closed 2 years ago.
I'm trying to achieve the flex layout as per the image below. In my code examples, I've not been successful, yet so I can't provide any useful code snippets.
Box 1 would be fixed width and 100% height
Box 2 and 3 would be 50% height and 100% width
Box 4 would be fixed width and 100% height
It would be wrapped in a container DIV (not shown).
Is this correct usage for Flex, or should a grid be used for something like this? I've found an example that manages to get either box 1 or box 4 in position (such as here: Mozilla Flex Example, but not with both.

For layouts with such requirements CSS Grid is a much better choice than Flexbox.
CSS Grid Layout excels at dividing a page into major regions or defining the relationship in terms of size, position, and layer, between parts of a control built from HTML primitives.
Here's a working codepen. You can modify the fixed columns width by changing the grid-template-columns definitions.

Yes, you can do this with flexbox - you will need a container div for box 2 and box 3. You can use something like this:
#layout {
display: flex;
resize: both;
overflow: scroll;
}
#box1, #box4 {
width: 100px;
}
#box2-3 {
flex-grow: 1;
display: flex;
flex-direction: column;
}
#box2, #box3 {
flex-grow: 1;
}
#box1, #box2, #box3, #box4 {
border: 1px solid red;
}
<div id="layout">
<div id="box1">Box 1</div>
<div id="box2-3">
<div id="box2">Box 2</div>
<div id="box3">Box 3</div>
</div>
<div id="box4">Box 4</div>
</div>

Related

CSS adapt the size of a div between two fixed divs [duplicate]

This question already has answers here:
Make a div fill the height of the remaining screen space
(41 answers)
Closed 7 months ago.
I have 3 divs:
<div>
<div id="div1">Title</div>
<div id="div2">Some text</div>
<div id="div3">Footer</div>
</div>
Every div have a width: 100%.
The title div height depends on its content so it can evoluate a little bit, and it has a fixed position.
The Footer div has a fixed size (its content cannot change) and a fixed position.
The goal is to have the text div between this two divs, having its size exactly matches the remaining places between title and text div so I can apply a scroll on it.
Can somebody explain to me how to do that ?
Thanks
I assume you want something like this:
#div1 {
background: rgba(0,0,250,0.2)
}
#div2 {
flex-grow: 1;
background: rgba(0,250,0,0.2);
overflow: scroll;
}
#div3 {
height: 10vh;
background: rgba(250,0,0,0.2);
}
.container {
height: 100vh;
flex-direction: column;
display: flex;
}
<div class="container">
<div id="div1">Title</div>
<div id="div2">Some text</div>
<div id="div3">Footer</div>
</div>
Judging by the clarification in your comment what you're trying to achieve is a basic layout which should be done using the <header> and <footer> tags rather than reinventing the wheel with divs.
However if you're set on using divs you should use position: absolute; or position: fixed; on the #div1 and #div3 depending on what you need the to do. Using this method you should add apropriate margins to make sure div1 and 3 dont cover div2.

Using flex-wrap:wrap but having trouble using pseudo selectors to adjust position of last item

We have an odd number of items inside of a flex: flex-wrap container and at a certain resolution when they wrap the last of the items is over to the left but I want it to (continue to) be to the right.
I googled and found a resource discussing a similar issue at: https://haizdesign.com/css/flexbox-align-last-item-grid-left/
The ::after pseudo-element they applied to achieve this is:
.speakers::after {
content: '';
flex: auto;
}
So I tried to apply this knowledge, but instead use the ::before pseudo-element to try to move my last item over to the right, but I could not get it to work. Below is some HTML and CSS code followed by a link to the CodePen:
#container {
display: flex;
flex-wrap: wrap;
}
.el-width {
min-width: 40%;
}
.last-el::before {
content: '';
flex: auto;
}
<div id="container">
<div class="el-width">Foo</div>
<div class="el-width">Bar</div>
<!-- uncomment to move Baz under Bar
<div class="el-width last-el"> </div>
-->
<div class="el-width last-el">Baz</div>
</div>
https://codepen.io/dexygen/pen/ExaNZYv
As you can see in the HTML if you interpose an actual (empty) div, Baz gets moved under Bar. I've also been able to introduce an actual element in my application and it does likewise. However I'd like to know how or if it can be achieved using ::before
This would be a lot easier with CSS Grid. I leave this here as an alternative answer, in case it helps others.
#container {
display: grid;
grid-template-columns: 40% 40%;
}
.el-width {
border: 1px solid;
}
.last-el {
grid-column-start: 2;
}
<div id="container">
<div class="el-width">Foo</div>
<div class="el-width">Bar</div>
<!-- uncomment to move Baz under Bar
<div class="el-width last-el"> </div>
-->
<div class="el-width last-el">Baz</div>
</div>
Pseudo elements on a flex container are treated as flex items (source).
So the first problem is that the pseudo element in your code is applied to the flex item (.last-el). It needs to be applied to the flex container (#container).
Then, the default order matters. The ::before() pseudo is the first flex item, and an ::after() pseudo would be the last.
So, if you're going to use a pseudo element as a flex item, to bump over an inner item, you need to use the order property to re-arrange the visual order. (Incidentally, this obviates the need to choose between ::before() and ::after().)
#container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.el-width {
flex: 0 0 33.33%;
}
#container::before {
order: 1;
flex: 0 0 33.33%;
content: '';
}
.el-width:nth-child(-n+3) {
order: 0;
}
.el-width:nth-last-child(-n+2) {
order: 2;
}
<div id="container">
<div class="el-width">Item 1</div>
<div class="el-width">Item 2</div>
<div class="el-width">Item 3</div>
<div class="el-width">Item 4</div>
<div class="el-width">Item 5</div>
</div>
The pseudo element method you're describing in your question is explained here:
Properly sizing and aligning the flex item(s) on the last row
A description of the problem, along with potential solutions, can be found here:
Targeting flex items on the last or specific row
And a clean and efficient solution for handling this problem, using CSS Grid, is here:
Equal width flex items even after they wrap
Fixing this is simple and to do it, we use a pseudo element. Going back to our container, (in this case, my container has a class of .speakers)
So they applied the ::after to the container to create a last element, not they apply to the last element last-el. And they did that because they used justify-content: space-between to justify their items leads their last element to unexpected position, which seems to not be of your case. If you want to layout in 2 dimensions, CSS Grid is the best. If you want better browser compatible, then you might already have the answer yourself in the codepen you gave. But I think what you really want might just be the answer that you basically can't solve this by just adding styles to .el-width::before?

Flex-box with the central element that fills all the free space [duplicate]

This question already has answers here:
Make a div fill the height of the remaining screen space
(41 answers)
Closed 4 years ago.
I am trying to design the web page with the following document tree (as to avoid the appearance of the scroll as much as possible):
html
head
body
div (flex-box - height 100%)
header (flex-child - fixed height)
main (flex-child - consumes all the remainig space/height)
footer (flex-child - fixed height)
Apparently, flex-box is the best solution, but I am reading this nice guide https://css-tricks.com/snippets/css/a-guide-to-flexbox/ and it appears that there are only limited options how to distribute the space (how to distribute the height of elements) - there are some "growth" properties but nothing else. How can I make the structure I am aiming to achieve? I have no code because I don't see the necessary CSS properties for making even a starter example.
I suppose this is what you're looking for. If you want to use flex you would set its direction to column, and set the height of the container as 100vh, then you set the flex-grow property to the body of the page so it uses the remaining space.
Better see it in full screen
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
header {
background: red;
height: 40px;
}
.body {
flex-grow: 1;
background: green;
}
footer {
background: blue;
height: 40px;
}
<div class="container">
<header>
</header>
<div class="body">
</div>
<footer>
</footer>
</div>

CSS grid height layout issue with grid item child height in Firefox 52 [duplicate]

This question already has answers here:
Why doesn't percentage padding / margin work on flex items in Firefox and Edge?
(2 answers)
Percentage padding / margin on grid item ignored in Firefox
(2 answers)
Closed 4 years ago.
I've recently redesigned my website utilizing CSS grid and I've come across a specific problem with FireFox 52. I know FireFox has issues, so I'm looking for some help on how to solve this little layout issue.
https://codepen.io/Krazyhawk/pen/qyJmWQ
Example HTML
<div class="grid">
<div class="item"><div></div></div>
<div class="item">
<p>Stuff</p>
<p>Stuff</p>
<p>Stuff</p>
<p>Stuff</p>
<p>Stuff</p>
<p>Stuff</p>
</div>
<div class="item"></div>
</div>
Example CSS
.grid {
width: 1200px;
display: grid;
grid-template-columns: 60% 1fr;
}
.item:first-child {
background-color: blue;
padding-right: 30px;
}
.item:first-child > div {
position: relative;
padding-bottom: 56.25%;
background-color: purple;
}
.item:nth-child(2) {
background-color: yellow;
}
.item:nth-child(3) {
background-color: grey;
grid-column: 1/3;
margin-top: 16px;
height: 50px;
}
I have two columns, and one underneath. The left column has a div in it that is used as an iframe container. To make that iframe responsive, it gets its height using a padding-bottom percentage. The right column is just a column with content, as well as the bottom one.
The issue lies with the padding-bottom percentage. The grid layout isn't recognizes the height of the div with padding-bottom, therefore the bottom bar doesn't allow enough space atop of it.
The solution solves itself if the left column has a height, but that's something I'd like to avoid. Giving it a height and keeping it responsive would likely require some JS and the resize event once the layout got down to tablet size (liquid layout).
As far as I know, this layout issue is specific to FireFox 52 (normally would cut it loose, but there is still a good chunk of user percentage).

Flexbox row: doesn't grow according to content? [duplicate]

This question already has answers here:
What are the differences between flex-basis and width?
(6 answers)
Closed 4 years ago.
I have the following structure, and I'd like to understand why my row does not grow with its inner content.
.row {
border:solid red;
display: flex;
flex-direction: row;
}
.cell {
border: solid green;
flex: 0 0 400px;
}
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
JsFiddle
I don't want the cells to grow or shrink, they should always be 400px width. The parent should grow and overflow the window, and an horizontal scrollbar is expected.
In the above example, the red border should be around the green border. The green border has the expected dimensions, not the red one.
I don't want to set a static width to my row for maintainability reasons related to my usecase.
I'm open for non-flexbox solutions (see inline-block attempt), but would appreciate more a flexbox one (because I need align-items: center behavior on the row)
If you want your container to always match the width of it's children, you'll need to look into display: inline-flex.
display: flex behaves more like a container with a width of 100%
Here's a fiddle that should work:
http://jsfiddle.net/hnrs64fm/

Resources