Is there any way to align cells in rows and columns (like in a table) using flexbox ?
To make things clear, what I would like is to align cells in the table below.
Of course I could add some flex: XXX but the problem is I don't want to fix the width of the columns.
I have gotten used to flex fixing everything but I feel kind of stuck... So is there no solution apart from going back to display: table or html <table>s...?
Here is a fiddle if you want to play with it :)
.myCell {
border: solid black 1px;
padding: 10px;
}
.myTable {
display: flex;
flex-direction: column;
}
.myRow {
display: flex;
flex-direction: row;
}
<div class="myTable">
<div class="myRow">
<div class="myCell">ROW 1, CELL 1</div>
<div class="myCell">ROW 1, CELL 2</div>
<div class="myCell">ROW 1, CELL 3</div>
</div>
<div class="myRow">
<div class="myCell">A LONGER CELL</div>
<div class="myCell">ROW 2, CELL 2</div>
<div class="myCell">ROW 2, CELL 3</div>
</div>
</div>
The future replacement for CSS Table is CSS Grid, not Flexbox.
That said, you can make Flexbox behave as a table, kind of, but not replace it fully, and as you seem to look for a column/row layout, use CSS Table (and that is not going back)
Related
This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
CSS when inline-block elements line-break, parent wrapper does not fit new width
(2 answers)
Closed 4 years ago.
I want to visualize source-code-like structures in HTML using some sort of "block" analogy. But for whatever reason I walk into some strange sizing issues with my flexboxes. The following snippet displays a visualisation of a program that would "normally" be printed like this:
while(true) {
goForward();
goForward();
goForward();
goForward();
goForward();
}
The outer box for the while is displayed as inline-flex to consume as little horizontal space as possible. But as you can see in the screenshot (or you may run the snippet yourself) there is quite a lot space wasted:
What I expect would look like this:
If you however click the goForward() blocks (which marks them with display: none), the width of the parenting block suddenly shrinks. From what I can tell it shrinks about as much as the width of the now hidden block.
The "linebreaks" between goForward() blocks are implemented using height: 0 but width: 100% elements. I also tried to do the breaks without empty elements and break-after: always, but this leads to the exact some behavior of the outer flexbox. I have observed this behavior in the most recent versions of Firefox and Chrome.
Why does the width of the outermost inline-flex element change (seemingly) with the number of items it displays vertically? And how could I "properly" implement this kind of layout where I basically want to have a block layout with arbitrary "linebreaks"?
// Hide blocks on click to demonstrate width changes
Array.from(document.querySelectorAll(".forward")).forEach(
elem => elem.addEventListener('click', () => elem.classList.add("hide"))
);
.code-block {
border: 2px solid blue;
border-radius: 5px;
padding: 5px;
display: inline-flex;
flex-flow: row wrap;
align-items: baseline;
}
.line-break {
width: 100%;
}
.forward {
cursor: pointer;
}
.hide {
display: none;
}
<div class="code-block">
<div class="terminal">while(</div>
<div class="code-block">true</div>
<div class="terminal">)</div>
<div class="line-break"></div>
<div class="code-block forward">
<div class="terminal">goForward()</div>
</div>
<div class="line-break"></div>
<div class="code-block forward">
<div class="terminal">goForward()</div>
</div>
<div class="line-break"></div>
<div class="code-block forward">
<div class="terminal">goForward()</div>
</div>
<div class="line-break"></div>
<div class="code-block forward">
<div class="terminal">goForward()</div>
</div>
<div class="line-break"></div>
<div class="code-block forward">
<div class="terminal">goForward()</div>
</div>
</div>
Instead of flex-flow: row wrap;, try flex-direction: column;. This gets each item to go vertically. Then wrap everything you want to be in a single "line" in its own inside of .code-block, to keep the contents of each line together. So,
<div class="code-block">
<div class="line-break">
<div class="terminal">while(</div>
<div class="code-block">true</div>
<div class="terminal">)</div>
</div>
...and so on for the others.
(You shouldn't need align-items: baseline; either.)
This question already has answers here:
The difference between flex:1 and flex-grow:1
(2 answers)
Nested column flexbox inside row flexbox with wrapping
(2 answers)
Closed 5 years ago.
Edit
Unlike The difference between flex:1 and flex-grow:1 . While the answer ultimately was the use of flex instead of flex-grow, my question was not the difference between the two but rather how to get nested flex-boxes to wrap appropriately. For someone struggling with this issue, there would be no way to find that answer on SO without already knowing the issue was the use of flex vs. flex-grow. If I already knew the issue was the difference between flex and flex-grow, I wouldn't have needed to ask the question.
Edit 2
If this post is going to be flagged as duplicate, it would be better to list it as a duplicate of Nested column flexbox inside row flexbox with wrapping instead of The difference between flex:1 and flex-grow:1.
I have a series of div tags that are defined as display:flex. They are laid out as a row with 3 columns. The first two columns are given a width and the third column is allowed to stretch to fill the rest of the space. The row is also set to wrap so that on smaller screens, the third column will wrap below the other two columns.
Here is some basic example code:
style.css
.flex-row {
display: flex;
flex-direction: row;
flex-grow: 1;
}
.flex-column {
display: flex;
flex-direction: column;
flex-grow: 1;
border: 1px solid lightgray;
}
.box {
display: flex;
height: 100px;
width: 300px;
min-width: 200px;
flex-shrink: 1;
border: 1px solid green;
}
index.html
<div class="flex-row" style="flex-wrap:wrap">
<div class="flex-column" style="flex-grow:0">
Column 1
</div>
<div class="flex-column" style="flex-grow:0;width:200px">
Column 2
</div>
<div class="flex-column">
<div class="flex-row" style="min-width:500px;flex-wrap:wrap">
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
<div class="box">Box 4</div>
<div class="box">Box 5</div>
<div class="box">Box 6</div>
<div class="box">Box 7</div>
</div>
</div>
</div>
(see my plnk here).
The last column contains a flex row with a series of "boxes" (see the example).
The desired effect is that as the screen is resized, the third column will continue to shrink down to the point where all the boxes are in a single column and the boxes have shrunk to their min-width. At that point, any further reduction in the screen width would cause the third column to wrap below the other two columns and it would then again expand to include as many boxes side by side as possible.
What seems to be happening in practice is that the third column wraps first -- before wrapping the contents it contains.
Here is a visual picture of what I'm want to see happen.
Is this possible to do with flexbox? If so, what am I doing wrong?
Here is what you desire. What you need to change :
For the flex-column it should be flex: 1; instead of flex-grow:1; and set a min-width to it. This way, it can grow and shrink both.
Using flex-grow:1 limits the container to only grow but not shrink and since you're using the flex-column class in the initial container i.e flex-row you need it to be flexible as the viewport is resized.
/* Styles go here */
.flex-row {
display: flex;
flex-direction: flex-row;
flex-grow: 1;
}
.flex-column {
display: flex;
flex-direction: column;
min-width:100px;
flex: 1;
border: 1px solid lightgray;
}
.box {
display:flex;
flex-shrink:1;
border: 1px solid green;
height:100px;
width:300px;
min-width:150px;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<div class="flex-row" style="flex-wrap:wrap">
<div class="flex-column" style="flex-grow:0">
Column 1
</div>
<div class="flex-column" style="flex-grow:0;width:200px">
Column 2
</div>
<div class="flex-column">
<div class="flex-row" style="min-width:500px;flex-wrap:wrap">
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
<div class="box">Box 4</div>
<div class="box">Box 5</div>
<div class="box">Box 6</div>
<div class="box">Box 7</div>
</div>
</div>
</div>
</body>
</html>
I am trying to make a little website that should have two columns, and each column should have its content centered.
However, I have noticed that the columns will follow the height of each other, and not act as individual columns. E.g. whenever I add content to one of the columns, the content of the other column will be moved to fit the height of that column.
In the JSFiddle, you can see that the "Hello" on the right side is not completely centered; it has been moved up to stand in line with the first of three "Hello"'s on the left side. I would like it so, that whenever I add content to one column, it doesn't affect the other - so the "Hello" on the right side should ideally stay completely centered.
JSFiddle: https://jsfiddle.net/goupb2ch/1/
I have worked on this for quite a while now. Any ideas? Thanks!
Consider using flexbox to solve your problem: in this case far less code is required.
https://jsfiddle.net/upwgk2u4/
.container {
display: flex;
text-align: center;
height: 100%;
}
.container > div {
flex: 1;
align-self: center;
}
Why not use what's already in Bootstrap 4? No extra CSS is needed.
https://www.codeply.com/go/0zwGz83Cbw
<div class="container">
<div class="row">
<div class="col-md-6 text-center">
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
</div>
<div class="col-md-6 align-self-center text-center">
<p>Hello</p>
</div>
</div>
</div>
I have been using bootstrap responsive 12 column grid layout for my website.
I have the layout like follows (stripped down version for example purpose)
<div class='container-fluid'>
<div class='row'>
<div class='col-md-1'>
Left side contents go here
</div>
<div class='col-md-11'>
Right side contents go here
</div>
</div>
</div>
What I need now, is that the left side column is wider than what I want. How can I make it fixed-length narrow and still use Bootstrap layout?
Any help is appreciated!
A clean solution would be customizing bootstrap to have more columns, like this answer:
How to use bootstrap with 16 or 24 columns
Other alternative is using nested rows, but that could end up with problems like unused space, so my suggestion is customizing bootstrap.
you can make a nested row within a column
For eg-
<div class="row">
<div class="col-md-1">
<div class="row">
<div class="col-md-offset-9 col-md-3"><!-- offset-9 leave space in left and start in last three of column --></div>
</div>
</div>
<div class="col-md-11"></div>
</div>
The issue you're having is an issue with how grid systems work. What they're designed to do is describe a fixed set of column widths: the content of those columns should expand to fill them. What you want is the inverse of this: you want the content to define the width.
You've effectively got three good options, and in order from least -> best in terms of getting what you want with the simplest markup:
Live with it (or have more columns as suggested, say 24).
Put the two columns of content in a block[1], apply display:table; width: 100%;. Make the two child items display:table-cell, use white-space:nowrap on the left-hand one and make the right-hand one width: 99%.
Put the two columns of content in a block[1], apply display:flex, and apply flex:1 to the right-hand child item.
Flex is the best solution, but needs IE10+ if that's an issue.
.container {
max-width: 400px;
margin: 0 auto;
}
[class^="row-"] {
margin: 10px 0;
}
.row-1 {
display: table;
width: 100%;
}
[class^="col-1-"] {
display: table-cell;
}
.col-1-left {
white-space: nowrap;
}
.col-1-right {
width: 99%;
}
.row-2 {
display: flex;
}
.col-2-right {
flex: 1;
}
<div class='container'>
<div class='row-1'>
<div class='col-1-left'>Some content</div>
<div class='col-1-right'>Some content</div>
</div>
<div class='row-2'>
<div class='col-2-left'>Some content</div>
<div class='col-2-right'>Some content</div>
</div>
</div>
I have a flexbox container with 2 columns. I want the columns to stack when there isn't room to display them both. I use the following html/css
<div class="container">
<div class="column">
<div>Short content</div>
<div>This is some longer content to show problem</div>
<div>Short contetn</div>
</div>
<div class="column">
<div>Short content</div>
<div>This is some longer content to show problem</div>
<div>Short contetn</div>
</div>
</div>
and
.container {
display: flex;
flex-wrap: wrap;
}
.column {
flex: 1 0 auto;
/* grow, don't shrink */
}
JS fiddle here: http://jsfiddle.net/AsdNS/
It seems that there is implicitally white-space: nowrap on the inner divs, but I don't want this. If I did want it surely I would specify it in my css. Is there a way to not wrap whitespace and then only wrap the columns if a single block of text with no whitespace is too big?
In practice I want to force it to wrap on some whitespace, but not others (I will use <span>s)
EDIT Here is a more real-world jsfiddle: http://jsfiddle.net/W7g3U/1/
What I want is for the long div to wrap, but the short divs not to.
EDIT 2 Here is what I want to achieve (works in chrome) http://plnkr.co/edit/Ppoe8xJrrbC16Y1vyWCD