Flexbox grid: two equal length rows, top row split into two columns - html

I'm trying to make a layout like the following image using css flexbox.
But I'm not much familiar with flexbox anyone can help me to make this?
Here is what I'm trying:
.row.flex {
display: flex;
}
.row [class=^"col-"] {
width: 200px;
height: 100%;
}
<div class="row flex">
<div class="col-xs-12 col-sm-6">
</div>
<div class="col-xs-12 col-sm-6">
</div>
<div class="col-xs-12 col-sm-12">
</div>
</div>
thanks :)

Option 1
Set the flex container to wrap.
Make each flex item take 50% of the space. Adjust for margins with calc.
The third item, which is forced to wrap, gets flex-grow: 1, so it consumes remaining space.
.row.flex {
display: flex;
flex-wrap: wrap;
}
.row [class^="col-"] {
flex: 0 0 calc(50% - 10px);
height: 100px;
margin: 5px;
background-color: lightgreen;
}
.row [class^="col-"]:last-child {
flex-grow: 1;
}
<div class="row flex">
<div class="col-xs-12 col-sm-6"></div>
<div class="col-xs-12 col-sm-6"></div>
<div class="col-xs-12 col-sm-12"></div>
</div>
Option 2
Set the flex container to wrap.
Give each flex item just enough width to allow only two per row.
Give each item the ability to consume remaining space.
.row.flex {
display: flex;
flex-wrap: wrap;
}
.row [class^="col-"] {
flex: 1 0 35%;
height: 100px;
margin: 5px;
background-color: lightgreen;
}
<div class="row flex">
<div class="col-xs-12 col-sm-6"></div>
<div class="col-xs-12 col-sm-6"></div>
<div class="col-xs-12 col-sm-12"></div>
</div>

Related

How to right align text inside a div for mutiline content using flexbox

I'm using flexbox model to align div items to the right. It works when the items has only one line, but when I have more than one line, only the first line is aligned right. If the div fills two or more lines the next lines get aligned to the left.
Notice the last div from first column, in bold.
Is that a way to get the multiline text right aligned for all the lines using flexbox?
/* CSS */
.wrapper {
display: flex;
flex-wrap: wrap;
width: 100%;
}
.col-md-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-md-9 {
flex: 0 0 65%;
max-width: 65%;
margin-left: 20px;
}
.item-first-col {
justify-content: flex-end;
border: 1px solid blue;
}
.item-second-col {
border: 1px solid blue;
}
.d-flex {
display: flex;
}
.align-items-center {
align-items: center;
}
<!-- HTML -->
<div class="wrapper">
<div class="item-first-col col-md-3 d-flex">
One line text
</div>
<div class="item-second-col col-md-9 d-flex align-items-center">
Second column text
</div>
<div class="item-first-col col-md-3 d-flex">
One line text
</div>
<div class="item-second-col col-md-9 d-flex align-items-center">
Second column text
</div>
<div class="item-first-col col-md-3 d-flex" style="font-weight: bold;">
Here goes the text that fills two lines
</div>
<div class="item-second-col col-md-9 d-flex align-items-center">
Second column text
</div>
</div>
Simply use text-align: right;
.wrapper {
display: flex;
flex-wrap: wrap;
width: 100%;
}
.col-md-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-md-9 {
flex: 0 0 65%;
max-width: 65%;
margin-left: 20px;
}
.item-first-col {
justify-content: flex-end;
border: 1px solid blue;
text-align: right;
}
.item-second-col {
border: 1px solid blue;
}
.d-flex {
display: flex;
}
.align-items-center {
align-items: center;
}
<div class="wrapper">
<div class="item-first-col col-md-3 d-flex">
One line text
</div>
<div class="item-second-col col-md-9 d-flex align-items-center">
Second column text
</div>
<div class="item-first-col col-md-3 d-flex">
One line text
</div>
<div class="item-second-col col-md-9 d-flex align-items-center">
Second column text
</div>
<div class="item-first-col col-md-3 d-flex" style="font-weight: bold;">
Here goes the text that fills two lines
</div>
<div class="item-second-col col-md-9 d-flex align-items-center">
Second column text
</div>
</div>
Thanks and best regards!
You can use text-align css property
/* CSS */
.wrapper {
display: flex;
flex-wrap: wrap;
width: 100%;
text-align: right;
}
.text {
text-align: right;
width: 100%;
}
.col-md-3 {
flex: 0 0 25%;
max-width: 25%;
}
.col-md-9 {
flex: 0 0 65%;
max-width: 65%;
margin-left: 20px;
}
.item-first-col {
justify-content: flex-end;
border: 1px solid blue;
}
.item-second-col {
border: 1px solid blue;
}
.d-flex {
display: flex;
}
.align-items-center {
align-items: center;
}
<!-- HTML -->
<div class="wrapper">
<div class="item-first-col col-md-3 text">
One line text
</div>
<div class="item-second-col col-md-9 align-items-center text">
Second column text
</div>
<div class="item-first-col col-md-3 text">
One line text
</div>
<div class="item-second-col col-md-9 align-items-center text">
Second column text
</div>
<div class="item-first-col col-md-3 text" style="font-weight: bold;">
Here goes the text that fills two lines
</div>
<div class="item-second-col col-md-9 align-items-center text">
Second column text
</div>
</div>
It is not possible to align text the way you want it using only Flexbox properties.
The reason for that appears in the Flexbox specification:
Each in-flow child of a flex container becomes a flex item, and each contiguous sequence of child text runs is wrapped in an anonymous block container flex item.
In your example, you are able to align a single line of text, but it is not the text that is aligned, it is the anonymous block which contains it. That's why it works.
It won't work for multiple lines of text because writing more text simply increases the size of the anonymous block and stretches to fill the whole parent div. At that point, it doesn't matter what value you set justify-content to.
The only way to do what you want is using text-align:right on the parent div which the anonymous block will inherit, making the text it contains align to the right.

How do I make one column in my flex table occupy less width than the others?

I'm trying to create an HTML table using DIVs and the flex CSS property. Roughly, all my rows look like
<div class='row'>
<div class='col'>
<div class='data-cell'>
Col A
</div>
</div>
<div class='col'>
<div class='data-cell'>
Col B
</div>
</div>
<div class='col'>
<div class='data-cell'>
Col C
</div>
</div>
<div class='col'>
<div class='data-cell'>
<div class='img-wrapper'>
<img src='images/delete.png' title='Delete' />
</div>
</div>
</div>
Below is the CSS I'm using
.row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
padding: 15px 0 15px 30px;
border-bottom: 1px solid $lightGrey
}
.col {
display: flex;
flex-direction: col;
flex-basis: 100%;
flex: 1;
}
.header-row {
color: $eclipse;
font-weight: bold;
}
.img-wrapper {
width: 100%;
text-align: right;
}
Right now the cells in each row take up 1/4th of the row width. What I would like to change is make the col with the image only be the size of the image and have the remaining rows even split up the remaining space. How do I do that using DIVs and flex?

Layout a flex box similar to a table?

I'm working with a framework developed in-house which depends on a certain structure to our HTML. And one of the tricky things is that each row needs its own container with its own classes and data attributes.
So here's the problem. Without drastically changing the DOM, how can I make the flex box below render essentially like an HTML table would? Or is a table the only way? The solution will have to work in both IE11 and Chrome.
I'm trying to make it look like this...
Column A | Column B | Column C
1 | 2 | 3
section {
display: flex;
flex-wrap: wrap;
}
section .col {
flex: 1 1 auto;
}
section .line-break {
flex-basis: 100%;
width: 0px;
height: 0px;
overflow: hidden;
}
<html>
<head>
</head>
<body>
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="line-break"></div>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
</body>
</html>
header, .row {
display: flex; /* aligns all child elements (flex items) in a row */
}
.col {
flex: 1; /* distributes space on the line equally among items */
}
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
If the content you are going to present is of type tabular data, then a table is the proper way.
HTML 5.1 W3C Recommendation, 1 November 2016, 4.9 Tabular data
Given that you can't, or don't want to, alter the markup, this can be done using CSS Table, and with that easily swap between any display type such as flex, block, etc., or even float, using media query etc.
I also removed the <div class="line-break"></div> element, since you don't need, though if it is rendered by a component or similar, leaving it as is won't cause any problem.
Using CSS Table
section {
display: table;
width: 100%;
}
section > * {
display: table-row;
}
section .col {
display: table-cell;
}
<html>
<head>
</head>
<body>
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
</body>
</html>
If you still need, or have to, use Flexbox, this answer of mine mention the difference between CSS Table and Flexbox on two important features:
Can flexbox handle varying sizes of columns but consistent row height?
Updated, a sample showing some useful Flexbox stuff, with varying width's and span columns.
Using Flexbox
.tbl {
display: flex;
flex-direction: column;
}
.row {
display: flex;
min-height: 50px;
}
.cell {
flex: 4;
border: 1px solid red;
}
.cell:nth-child(1) {
flex: 1;
}
.cell:nth-child(2) {
flex: 2;
}
.cell.span4-5 {
flex: 8 24px; /* col 4,5 flex-grow/border/padding */
}
.cell.span3-4 {
flex: 8 24px; /* col 3,4 flex-grow/border/padding */
}
.cell.span3-5 {
flex: 12 36px; /* col 3,4,5 flex-grow/border/padding */
}
.row:first-child .cell {
display: flex;
justify-content: center; /* center horiz. */
align-items: center; /* center vert. */
}
.row .cell {
padding: 5px;
box-sizing: border-box;
}
<div class="tbl">
<div class="row">
<div class="cell">ID </div>
<div class="cell">Nr </div>
<div class="cell">Header 1 </div>
<div class="cell span4-5"> Header 2 </div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">Content</div>
<div class="cell">Content</div>
<div class="cell">Content</div>
</div>
<div class="row">
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell span3-5">Content</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell span3-4">Content</div>
<div class="cell">Content</div>
</div>
</div>
This code works for me:
* {
box-sizing: border-box;
}
body, html {
height: 100%;
margin: 0;
}
#container {
width: 400px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
background-color: lightgrey;
padding: 10px;
}
.shelf {
flex: 1 1 auto;
width: 100%;
margin-bottom: 10px;
border: 1px solid black;
background-color: lightgreen;
display: flex;
flex-direction: row;
}
.shelf:last-child {
margin-bottom: 0;
}
.labelbox {
flex: 0 0 35%;
}
.valuebox {
flex: 0 0 65%;
}
<div id="container">
<div class="shelf">
<div class="labelbox">Name: </div> <div class="valuebox">Barry Carter</div>
</div>
<div class="shelf">
<div class="labelbox">DOB:</div><div class="valuebox">10/12/1980</div>
</div>
<div class="shelf">
<div class="labelbox">
Description:
</div>
<div class="valuebox">
This content goes on and on and will force the height to expand. And the label box to the left will
"move" with it. There need not be much of a relation other than that their parent div/flex-container is
getting taller as well.
</div>
</div>
<div class="shelf">
<div class="labelbox">Group:</div><div class="valuebox">Advanced</div>
</div>
<div class="shelf">
<div class="labelbox">End Date:</div><div class="valuebox">2020-09-20</div>
</div>
</div>
Use CSS Grid. You can style any table the way you like.
Keep in mind If your table is more than 700 rows, the fram rate will start to drop, no matter what js framework you use. react, angular, vue or vanila JS. the scrolling will get real laggy.
And the maximum you row can use is 1000. More than that the extra row will create bad graphic. But you wont reach 1000 anyway, because at 700th row, the scrolling speed, starts to get bad.
If somehow you need to display more than 1000 rows, you will visualized lib. Every js framework has a lib to do so. Basically, it will render the rows in the view port. The rows that not in the view port will not be rendered. They will only be rendered when user scrolls.
This is year 2021, chances you read this answer in the future, the browsers vendor might probably fix the performance of 1000 rows, they might even extend that limit. So try it out.

How to use `flex: grow` on floating content?

I have a header with 2 rows of 2 Foundation columns of content, as below:
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
HEADER
</div>
<div class="large-6 columns">
menu
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
The .header height is dynamic and not set. I want the .image element to take up 100% of the remaining vertical space.
eg:
To that affect I have tried using flex and flex-grow, eg:
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
}
.image-container {
flex-grow: 1;
}
but had no luck, see fiddle: https://jsfiddle.net/9kkb2bxu/46/
Would anyone know how I could negate the dynamic height of the header from the 100vh of the image container?
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
border: 1px solid black;
display: flex;
}
.image {
background-color: red;
flex-grow: 1;
width: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet"/>
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
Set the second row to take up the rest of the remaining height with flex: 1 and make sure you nest that flex with display: flex:
.row.target-row {
flex: 1;
display: flex;
}
Set the .image-container to 100% height of its column parent.
.image-container {
height: 100%;
}
By default both columns will expand. Stop the left column from expanding with:
.large-5 {
align-self: flex-start;
}
(flex-start reference: https://stackoverflow.com/a/40156422/2930477)
Complete Example
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
height: 100%;
background-color: red;
}
.large-5 {
align-self: flex-start;
}
.row.target-row {
flex: 1;
display: flex;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet" />
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row target-row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
flex-grow only applies to flex children.
.image-container isn't a direct child of a display: flex element, so that property has no effect.
Plus, it affects the flex axis, which is not what you want.
Instead, you need to put those two elements in their own flex row, and use align-items (on the parent) and align-self (on either child) so that the first one aligns (on the cross axis) to flex-start (stick to top) and the second one to stretch.
You'll also want that flex row (parent) to have flex-grow: 1 so that it stretches along the vertical flex axis of its parent (.wrapper) to fill the rest of the page (otherwise, the grandchild will have nothing to stretch to).
For more information, read a good flex tutorial.
div.wrapper > div:not(.header).row {
flex: 1; /* 1 */
display: flex; /* 1 */
}
div.large-7.columns {
display: flex; /* 2 */
}
div.image-container { /* 3 */
flex: 1;
}
div.large-5.show-for-medium { /* 4 */
align-self: flex-start;
}
jsFiddle
Notes:
flex container and items consume all remaining height of respective parents
give children full height (via align-items: stretch initial setting)
flex item consumes all available width
yellow box does not need to expand to full height; now set to content height

Flexbox breaks bootstrap responsiveness

I have a row where one column can vary in height so I don't know how high it will be. In order to properly space the adjacent column I have used nested flex boxes.
This works fine on main break point but as soon as I add the flex box then this breaks the responsiveness as the columns don't stack on mobile anymore.
What should I do here? Should I drop flexbox? How else can I achieve this spacing?
.container{
margin-top: 60px;
}
.container{
border: 1px solid #000;
}
.row{
display: flex;
}
.row-center{
display: flex;
flex: 1;
}
.outer{
display: flex;
flex-direction: column;
justify-content: space-around;
border: 1px solid #000;
width: 100%;
}
.one, .two, .three{
flex: 0 0 40px;
border: 1px solid #000;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-6"><img src="http://placehold.it/350x500"></div>
<div class="col-xs-12 col-sm-6 row-center">
<div class="outer">
<div class="one">some text</div>
<div class="two">some text</div>
<div class="three">some text</div>
</div>
</div>
</div>
</div>
jsfiddle mirror: https://jsfiddle.net/y68dnzwy/
May be this help you:
.container{
margin-top: 60px;
}
.container{
border: 1px solid #000;
}
.row{
display: flex;
}
.row-center{
display: flex;
flex: 1;
}
.outer{
display: flex;
flex-direction: column;
justify-content: space-around;
border: 1px solid #000;
width: 100%;
}
.one, .two, .three{
flex: 0 0 40px;
border: 1px solid #000;
}
/* Added: */
#media screen and (min-width:100px) and (max-width: 980px) {
.row-center {
flex: auto;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-6"><img src="http://placehold.it/350x500"></div>
<div class="col-xs-12 col-sm-6 row-center">
<div class="outer">
<div class="one">some text</div>
<div class="two">some text</div>
<div class="three">some text</div>
</div>
</div>
</div>
</div>
Demo
Used this with bootstrap 3, 4-text boxes in row with same height depending on the dynamic text, where on tablet and mobile are only 2 in row. And with tetx centered in middle
Somehow this flex magic makes on mobile, that only text boxes that are in same row have same height, so if last item is super tall, only last 2 items are super tall, not affecting first 2.
<div class="row row-flex-box">
<div class="col-xs-6 col-sm-6 col-md-3">
<div class="thumbnail flex-col-vertical-center">
<div class="caption"><span>text text text text</span></div>
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-3">
<div class="thumbnail flex-col-vertical-center">
<div class="caption"><span>text text text text text text text text</span></div>
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-3">
<div class="thumbnail flex-col-vertical-center">
<div class="caption"><span>text text text text</span></div>
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-3">
<div class="thumbnail homepage-slider-bottom-block-single flex-col-vertical-center">
<div class="caption"><span>text text text texttext text text texttext text text text</span></div>
</div>
</div>
</div>
Css:
.row-flex-box {
display: flex; /* make cols same heigh */
flex-wrap: wrap; /* alows responsive behavior of cols (otherwise cols will never break on mobile)*/
}
.flex-col-vertical-center {
display: flex; /* specifing display/flex-direction/justifi-content only because i want to have text aligned in the middle of boxes much cleaner than display:table-cell way*/
flex-direction: column;
justify-content: center;
text-align:center;
height: 100%; /* since cols have bigger height this has effect, also can be ussefull - height: calc(100% - 15px); with 15px bottom margin */
}