CSS: Using flexbox for structure content - html

I want to create a layout like below image. It includes:
A left part
A right part
A title stretch whole row
I can do as structure html like this and using some layout such as Flexbox, div positioning ...
<div class="wrapper">
<div class="status">
<div class="left">12/05/2015</div>
<div class="right>Adventure Story</div>
</div>
<div class="title">A long story about the Atlantic</div>
</div>
I just learn Flexbox and I want to simplify to this html (no wrapper against the first row)
<div class="wrapper">
<div class="left">12/05/2015</div>
<div class="right>Adventure Story</div>
<div class="title">A long story about the Atlantic</div>
</div>
Can I use Flexbox for above html structure. If yes, please tell me how.

You can simply do this :
.wrapper {
display: flex;
flex-wrap: wrap; /* to avoid overflow and force title going to new line */
}
.left,
.right {
flex: 0 0 50%; /*each element will take 50% of the width */
}
.right {
text-align: right;
}
.title {
flex: 0 0 100%; /*this element will take 100% of the width*/
}
div {
border: 1px solid red;
box-sizing: border-box;
}
<div class="wrapper">
<div class="left">12/05/2015</div>
<div class="right">Adventure Story</div>
<div class="title">A long story about the Atlantic</div>
</div>

You can use flex-wrap: wrap on flex-container and flex: 0 0 100% on title element so that it goes to new row and margin-left: auto on second element in order to position it to the right side.
.wrapper {
display: flex;
flex-wrap: wrap;
}
.title {
flex: 0 0 100%;
}
.right {
margin-left: auto;
}
<div class="wrapper">
<div class="left">12/05/2015</div>
<div class="right">Adventure Story</div>
<div class="title">A long story about the Atlantic</div>
</div>

Related

Align all the fields in a line after applying word-break prop in css

I have 2 spans inside a div:
html:
<div class="main">
<span class="title"> Name</span>
<span class="values">/sys/fs/cgroup/sys/fs/</span>
</div>
here is how it looks:
http://jsfiddle.net/tdrgz1yj/
as you can see the size and volume title getting pushed down when I have long text for Name field. Also I cannot increase the width any more cause in actual app, the Volume field goes out of focus.
Is there a way I can align the Name, Size and Volume fields all in one line even after applying the word-break prop?
Can I make it look something like with css?
Thanks!
Yes. Just add display: flex to the .parent
Example
If you want to move the long text to the same line with the "Name" title, set display: flex to the .main as well.
Example 2
I suggest using span only to wrap inline elements. Instead, use divs :
.parent {
padding: 20px 10px;
margin: 0 0 20px;
display: flex;
width: 100%;
box-sizing: border-box;
}
.parent div {
margin-left: 20px;
}
.main {
flex-basis: 200px;
flex-grow: 1;
flex-shrink: 0;
display: flex;
}
.title {
margin-right: 20px;
display: inline-block;
}
.values {
word-break: break-word;
}
<div class="parent">
<div class="main">
<div class="title">Name:</div>
<div class="values">/sys/fs/cgroup/sys/fs//sys/fs/cgroup/sys/fs//sys/fs/cgroup/sys/fs/</div>
</div>
<div class="main">
<div class="title">Size:</div>
<div class="values">223k</div>
</div>
<div class="main">
<div class="title">Volume:</div>
<div class="values">111</div>
</div>
</div>

place two divs per row

so I have X divs and I want to put 2 divs in one row next to each other. If the screen size width is below n px there should be 1 div per row.
Currently I have this
#container {
display: flex;
}
.box {
width: 50px;
background: red;
}
#media(max-width: 300px) {
#container {
display: block;
}
}
<div id="container">
<div class="box"> 1 </div>
<div class="box"> 2</div>
<div class="box"> 3 </div>
<div class="box"> 4 </div>
</div>
How can I limit the flex box to two divs per row?
Add 50% width on .box and flex-wrap:wrap on the container
Additionally, what you did by changing display: flex to block was not required. Just change the .box elements width to 100%
#container {
display: flex;
flex-wrap: wrap;
}
.box {
width: 50%;
background: red;
}
#media(max-width: 300px) {
.box {
width: 100%;
}
}
<div id="container">
<div class="box"> 1 </div>
<div class="box"> 2</div>
<div class="box"> 3 </div>
<div class="box"> 4 </div>
</div>
Just add a property in your container class like
.container {
display: flex;
flex-wrap: wrap;
}
And in box class just specify the width of your box as 50% like
.box {
width: 50%;
background: red;
}
That should do the trick.
Flex will do a trick for you. flex-wrap: wrap for #container will make children wrap when necessary. .box with 50% and after breakpoint 100%.`
According to MDN:
The CSS flex-wrap property specifies whether flex items are forced into a single line or can be wrapped onto multiple lines. If wrapping is allowed, this property also enables you to control the direction in which lines are stacked.
If you are new to flexbox I recommend this guide.
Snippet
#container {
display: flex;
flex-wrap: wrap;
}
.box {
width: 50%;
background: red;
}
#media(max-width: 300px) {
.box {
width: 100%;
}
}
<div id="container">
<div class="box"> 1 </div>
<div class="box"> 2 </div>
<div class="box"> 3 </div>
<div class="box"> 4 </div>
</div>

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

Make div in div in div scrollable with overflow

I have an React application and having a slightly bigger problem with some CSS stuff.
I have an view which is divided in 2 parts. But those two parts are lying in one bigger component. The left part is displaying some contacts and on the right I want to display details of those contacts. Now I want to make the left part scrollable like a list, but the right part just stay fixed on its position. Also the height of the left part should always stay as high as the current screen size. I am using Bulma CSS as my base CSS framework.
This is my HTML:
<div class="pane main-content" id="mainPane">
<div class="contacts-view">
<h1 class="title">My Title</h1>
<div class="">Other Stuff</div>
<div class="columns">
<div class="column is-3">
<div class="columns is-multiline">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
</div>
<div class="column is-9"></div>
</div>
</div>
</div>
This is a quick sketch of how it looks:
Current relevant CSS:
.main-content {
background-color: #fff;
padding: 20px;
}
.pane {
position: relative;
overflow-y: auto;
flex: 1;
}
.columns {
margin-left: -0.75rem;
margin-right: -0.75rem;
margin-top: -0.75rem;
}
.column {
display: block;
-ms-flex-preferred-size: 0;
flex-basis: 0;
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
-ms-flex-negative: 1;
flex-shrink: 1;
padding: 0.75rem;
}
For better explanation. The component with class column is-3 should be scrollable but all other parts should stay fixed with no scroll.
I tried:
.is-3
overflow:hidden;
overflow-y:scroll;
But I found out that I have to set the height of is-3 because otherwise my screen is just expanded to the bottom. But I can not set a fixed height to it, because my screen size is dynamic and depended on the size of #mainPane. But I can also not set it to 100% because then the screen is also expanded at the bottom. Do you have any suggestions how I can solve this with CSS ?
Thanks in advance :)
You can use flexbox layout.
jsFiddle
body {
margin: 0;
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
.header {
background: lightblue;
}
.content {
flex: 1;
display: flex;
min-height: 0; /*ADDED 2021*/
}
.sidebar {
background: lightgreen;
overflow: auto;
}
.main {
flex: 1;
background: pink;
overflow: auto;
}
<div class="container">
<div class="header">header</div>
<div class="content">
<div class="sidebar">
<div style="height:200vh;">sidebar</div>
</div>
<div class="main">
<div style="height:200vh;">main</div>
</div>
</div>
</div>

Flexbox many nested children

I've read many posts on flexbox but still have an issue that bugs me.
I want to have a sticky footer using flexbox as per this guide.
But then, inside my page content I would like to have as many nested divs I like and have them taking the same height of the parent.
The problem is, setting height: 100% on each child (as I would do in a non-flexbox scenario) works differently when flexbox is enabled. This results in the children getting more height (overflow the parent).
To make this more clear here's a codepen without flexbox
and a codepen with flexbox
You can see in the flexbox scenario the footer gets the green bakground even if I don't want that.
HTML:
<div class="sticky-footer-container">
<div class="sticky-footer-content">
<div class="page-container">
<div class="main-menu">
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sticky-footer">
Some footer content
</div>
</div>
SCSS:
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
background: silver;
padding: 0;
margin: 0;
}
.sticky-footer-container {
height: 100%;
display: flex;
flex-direction: column;
.sticky-footer-content {
height: 100%;
background: blue;
flex: 1;
div {
height: 100%;
}
.main-menu-selection {
height: 50%;
}
}
}
.some-other-class {
background: green;
}
In order to solve this, ANY nested div has to become a flex-container ?
In other words, is there any way to "stop the flex propagation" at some point of the tree, so all the divs gets the parent height without overflow?
display:flexbox is not really a valid value :)
you need to set height as well and eventually inherit it from html :
.sticky-footer-container {
display: flex;
flex-direction: column;
}
.sticky-footer-content {
flex: 1;
}
/* let's inherit some height to pull the footer down */
html,
body,
.sticky-footer-container {
height: 100%;
margin: 0;
}
.sticky-footer {
display: flex;/* flex item can be flexboxes as well */
background: turquoise;
align-items: center;
justify-content: center;
min-height: 3em;
}
<div class="sticky-footer-container">
<div class="sticky-footer-content">
<div class="page-container">
<div class="main-menu">
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sticky-footer">
Here my footer
</div>
</div>