CSS flexbox and justify-content [duplicate] - css

This question already has answers here:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
(6 answers)
Closed 4 months ago.
For a layout, I need to have three flex items (rows) in a flex container, and I want them justified as space-between... The first row will contain some cloud tags, the second a price, and the third a Read more link.
But there will be cases where for specific items, only the last row (the Read more) will need to exist.
So, in those cases, for uniformity, I want the Read more link to be placed at the bottom of the container; but space-between doesn't help much towards that approach...
What can I do to have a fallback justify-content property set to end for when there is only one child item?
.container {
background-color: #aaa;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
height: 200px;
margin-bottom: 20px;
}
.tags {
display: flex;
}
.tags span {
background-color: #f0f;
padding: 10px;
margin: 0 0 0 10px;
}
.price {
display: flex;
background-color: #ff0;
padding: 10px;
font-size: 150%
}
.read-more {
display: flex;
background-color: #0ff;
padding: 10px;
}
<div class="container">
<div class="tags">
<span>tag 1</span><span>tag2</span><span>tag 3</span>
</div>
<div class="price">
$100
</div>
<div class="read-more">
Read more >>
</div>
</div>
<div class="container">
<div class="read-more">
Read more >>
</div>
</div>

If you are able/willing to change the order of the flex-items in your HTML code, you can reverse them there and use flex-direction: column-reverse; on the container. That way the "read more" element is the first flex-item and due to the reversed direction at the bottom of the container:
.container {
background-color: #aaa;
display: flex;
flex-direction: column-reverse;
justify-content: space-between;
align-items: flex-end;
height: 200px;
margin-bottom: 20px;
}
.tags {
display: flex;
}
.tags span {
background-color: #f0f;
padding: 10px;
margin: 0 0 0 10px;
}
.price {
display: flex;
background-color: #ff0;
padding: 10px;
font-size: 150%
}
.read-more {
display: flex;
background-color: #0ff;
padding: 10px;
}
<div class="container">
<div class="read-more">
Read more >>
</div>
<div class="price">
$100
</div>
<div class="tags">
<span>tag 1</span><span>tag2</span><span>tag 3</span>
</div>
</div>
<div class="container">
<div class="read-more">
Read more >>
</div>
</div>

You can give the container a position: relative; tag, the .read-more class, and the :only-child pseudo class. Then when it is the only child in the container, it will add the attributes position:absolute; bottom:0; right:0; to it.
This moves it to the bottom right of the container. The justify-content: end !important; doesn't move the container to where you want it to be.
Example:
.container {
background-color: #aaa;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
height: 200px;
margin-bottom: 20px;
position:relative;
}
.tags {
display: flex;
}
.tags span {
background-color: #f0f;
padding: 10px;
margin: 0 0 0 10px;
}
.price {
display: flex;
background-color: #ff0;
padding: 10px;
font-size: 150%
}
.read-more {
display: flex;
background-color: #0ff;
padding: 10px;
}
.read-more:only-child{
position:absolute;
bottom:0;
right:0;
}
<div class="container">
<div class="tags">
<span>tag 1</span><span>tag2</span><span>tag 3</span>
</div>
<div class="price">
$100
</div>
<div class="read-more">
Read more >>
</div>
</div>
<div class="container">
<div class="read-more">
Read more >>
</div>
</div>

Related

How to control the space between flex items

I'm just doing some learning material on Codeacademy and I'm wanting to know how to control the space between the "locations" text and the three divs below. The assignment is asking me to create a 15px space between them but I don't know how to do that. Currently, there is just a default space that I don't know how is calculated.
html {
text-align: center;
}
.location-container {
background-image: url(https://content.codecademy.com/courses/freelance-1/unit-4/img-locations-background.jpg);
height: 700px;
width: 1200px;
display: flex;
justify-content: center;
align-content: center;
flex-wrap: wrap;
}
#local {
background-color: blueviolet;
}
.location-columns {
display: flex;
justify-content: center;
width: 100%;
gap: 30px;
color: white;
}
.locations {
background-color: black;
width: 300px;
}
<div class="location-container">
<h2 id="local">Locations</h2>
<div class="location-columns">
<div class="locations">
<h3>Downtown</h3>
<h5>384 West 4th St</h5>
<h5> Suite 108</h5>
<h5>Portland, Maine</h5>
</div>
<div class="locations">
<h3>East Baysuide</h3>
<h5>3433 Phisermans Avenue</h5>
<h5>(Northwest Corner)</h5>
<h5>Portland, Maine</h5>
</div>
<div class="locations">
<h3>Oakdale</h3>
<h5>515 Crescent Avenue</h5>
<h5> Second Floor</h5>
<h5>Portland, Maine</h5>
</div>
</div>
Thanks for any insights.
Heading elements come with large upper and lower margins right from the default browser styles.
You can remove those for elements inside .locations, make it a flex container and use row-gap to control vertical spacing:
html {
text-align: center;
}
.location-container {
background-image: url(https://content.codecademy.com/courses/freelance-1/unit-4/img-locations-background.jpg);
height: 700px;
width: 1200px;
display: flex;
justify-content: center;
align-content: center;
flex-wrap: wrap;
}
#local {
background-color: blueviolet;
}
.location-columns {
display: flex;
justify-content: center;
width: 100%;
gap: 30px;
color: white;
}
.locations {
background-color: black;
display: flex;
flex-direction: column;
row-gap: 30px;
padding: 30px;
width: 300px;
}
.locations>* { margin: 0; }
<div class="location-container">
<h2 id="local">Locations</h2>
<div class="location-columns">
<div class="locations">
<h3>Downtown</h3>
<h5>384 West 4th St</h5>
<h5> Suite 108</h5>
<h5>Portland, Maine</h5>
</div>
<div class="locations">
<h3>East Baysuide</h3>
<h5>3433 Phisermans Avenue</h5>
<h5>(Northwest Corner)</h5>
<h5>Portland, Maine</h5>
</div>
<div class="locations">
<h3>Oakdale</h3>
<h5>515 Crescent Avenue</h5>
<h5> Second Floor</h5>
<h5>Portland, Maine</h5>
</div>
</div>

Flexbox, wrap items by column [duplicate]

This question already has answers here:
Layout possible? Flexbox vs Float layout with multiple columns and rows
(3 answers)
Left column and stacked right column using flexbox CSS [duplicate]
(2 answers)
Closed 4 years ago.
I am trying to control the position of some blocks contained in a wrapper with flexbox functionalities. Here is what I want at the end:
Here is the markup I would like to use. I wish not to change it and visually organize my box with CSS:
<div class="wrapper">
<div class="list-1">
Liste 1
</div>
<div class="list-2">
Liste 2
</div>
<div class="list-3">
Liste 3
</div>
</div>
I tried multiple things but it does not work. Here is the closest thing I came with, but list-3 only starts when list-2 also starts:
.wrapper {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
}
div[class^="list-"] {
text-align: center;
}
.list-1 {
background: red;
flex-basis: 80%;
line-height: 50px;
}
.list-2 {
background: pink;
flex-basis: 80%;
line-height: 50px;
}
.list-3 {
background: green;
flex-basis: 20%;
line-height: 100px;
}
<div class="wrapper">
<div class="list-1">
Liste 1
</div>
<div class="list-2">
Liste 2
</div>
<div class="list-3">
Liste 3
</div>
</div>
Is it even possible? Thank you for your help.
try this code
add div to first and second list and use flex-basis:80% for new div
i add class
.list {
flex-basis: 80%;
}
.wrapper {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
}
div[class^="list-"] {
text-align: center;
}
.list-1 {
background: red;
flex-basis: 80%;
line-height: 50px;
}
.list-2 {
background: pink;
flex-basis: 80%;
line-height: 50px;
}
.list-3 {
background: green;
flex-basis: 20%;
line-height: 100px;
}
.list {
flex-basis: 80%;
}
<div class="wrapper">
<div class="list">
<div class="list-1">
Liste 1
</div>
<div class="list-2">
Liste 2
</div>
</div>
<div class="list-3">
Liste 3
</div>
</div>
.wrapper {
display: flex;
flex-wrap: wrap;
align-items: stretch; /* this is for the children of flex to be of equal height. */
}
div[class^="list-"] {
text-align: center;
}
.list-1 {
background: red;
line-height: 200px;
height:200px;
}
.list-2 {
background: pink;
line-height: 100px;
height:100px;
}
.list-3 {
background: green;
flex-basis: 20%;
/* following 3 codes is for centered the liste3. deletable */
display:flex;
align-items:center;
justify-content:center;
}
.column {
display:flex;
flex-direction:column;
flex:4;
}
<div class="wrapper">
<div class="column">
<div class="list-1">
Liste 1
</div>
<div class="list-2">
Liste 2
</div>
</div>
<div class="list-3">
Liste 3
</div>
</div>

How to set two elements be next each other using flexbox

I'm trying to make my css with flexbox, so I followed some articles and tried to set my elements like this example:
the elements 1 & 2 are in another container
I'm trying to set the two elements (1 and 3) to be next each other as the second example (The first is what I have now and the other is what I'm trying to achieve.)
but I can't find a good way with the Flexbox since I set the container to flex-direction: column;
<div class="container">
<div class="sub-ctn">
<h5 class="1"><span>♦ </span>{{ text }}</h5>
<span class="2">{{ value }}</span>
<div class="3">
<h5>{{ text }}
</div>
</div>
</div>
CSS:
.container {
margin-right: 2.5%;
direction: rtl;
}
.sub-ctn {
display: flex;
flex-flow: row;
margin-top: 1%;
flex-direction: column;
}
.1 {
width: 100%;
direction: rtl;
text-align: right;
}
.2 {
float: right;
/* text-align: right; */
}
.3 {
margin-left: 1%;
display: flex;
flex-direction: column;
}
let me know if another information is needed
Don't use float and flex together. Flex alone will be much easier and better.
.cont{
display: flex;
width: 80%;
border: 1px solid black;
padding: 10px;
}
.left-cont{
height: 100%;
flex-grow: 1;
}
.right-cont{
flex-grow: 1;
display: flex;
flex-direction: column;
}
.item{
text-align: center;
border: 1px solid black;
margin: 3px;
}
<div class="cont">
<div class="left-cont">
<div class="item">3</div>
</div>
<div class="right-cont">
<div class="item">1</div>
<div class="item">2</div>
</div>
</div>

Display table on flex item

My question is simple. Is it possible to have display: table on a flex item?
When I set it on an item, the layout doesn't work as expected - the second flex item doesn't grab the available vertical/horizontal space.
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
flex: 1;
display: table;
background-color: red;
}
.content > span {
display: table-cell;
vertical-align: middle;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>
Of course you can, but not necessarily a good solution though.
May I suggest you use flex all the way.
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
flex: 1;
background-color: red;
display: flex;
align-items: center;
justify-content: center;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>
Side note:
A table element is special and doesn't behave as normal block or inline elements. To make it work with display: table, you need to set a height to your parent as well as to the table, like in this sample, http://jsfiddle.net/LGSon/0bzewkf4.
Still, as you can see, the table height is 200px because flex has some flaws when it comes to limit height's, so it is not display:table that breaks your flex, it is flex who is somewhat broken.
Here is another answer of mine, showing yet another workaround where flex doesn't behave: Normalizing Flexbox overflow in IE11
It's a big question why you use table in flexbox...
But you can set width to your table and inherit min-height from parent
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
display: table;
flex:1;
background-color: red;
width:100%;
min-height:inherit;
}
.content > span {
display: table-cell;
vertical-align: middle;
height: 100%;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>
You should not need to use a table layout at all here. Just add align-self: center; to .content- > span {.... And make the span element become a flex item as well, by adding display:flex to the .content element. The reason why the table layout is not working for you is because vertcal-align has no effect on the alignment of flex items. So mixing a flex-layout with a table-layout by changing the display property of a flex-item seems not to be a good idea, because you are loosing the flexibility of the flex-layout.
Properties not affecting flexible boxes
Because flexible boxes use a different layout algorithm, some properties do not make sense on a flex container:
column-* properties of the multiple column module have no effect on a flex item.
float and clear have no effect on a flex item. Using float causes the display property of the element to compute to block.
vertical-align has no effect on the alignment of flex items.
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
flex: 1;
display: flex;
background-color: red;
}
.content > span {
flex: 1;
align-self: center;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>
Tables are row or horizontally oriented so wouldn't you get weird results if placed within a flex-column? I changed everything to a good old block, they stack very well in a column flow--vertical harmony.
.content is dead center by using: position: relative; top: 50%; and translateY(360%); for vertical and text-align: center; for horizontal. Oh and of course turning that span into a useful block.
Changed the following:
.content {
flex: 1;
background-color: red;
}
.content > span {
display: block;
position: relative;
top: 50%;
transform: translateY(360%);
text-align: center;
}
I changed display: table to table-row is this what you wanted?
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
flex: 1;
background-color: red;
}
.content > span {
display: block;
position: relative;
top: 50%;
transform: translateY(360%);
text-align: center;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>

CSS - Horizontally and vertically distribute divs

So I've got this header with three elements in them.
What I want is basically this:
http://jsfiddle.net/zktbfmqo/2/
Only with vertically centered content in each of the divs as well.
Is there an easy and clever way to do this without using absolutes etc?
Vertical-align: middle doesn't seem to do much, but that property isn't always easy to work with either.
HTML:
<div id="container">
<div class="box1">Text</div>
<div class="box2">Text</div>
<div class="box3">Text</div>
<span class="stretch"></span>
</div>
CSS:
#container {
border: 2px dashed #444;
height: 125px;
text-align: justify;
-ms-text-justify: distribute-all-lines;
text-justify: distribute-all-lines;
min-width: 612px;
}
.box1, .box2, .box3 {
width: 150px;
height: 125px;
vertical-align: middle;
display: inline-block;
*display: inline;
zoom: 1;
text-align: center;
}
.stretch {
width: 100%;
display: inline-block;
font-size: 0;
line-height: 0
}
First you can achieve the same result in a better way by using Flexbox.
For vertical align text to the middle you can simply approach that by adding the line-height property and set it to the same exact height of the container div so in your case it would be 125px or if you used flexbox it can be done with align-items: center , and here is the final code:
.wrapper {
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row nowrap; /* Safari 6.1+ */
flex-flow: row nowrap;
-webkit-justify-content: space-between; /* Safari 6.1+ */
justify-content: space-between;
font-weight: bold;
height: 125px;
min-width: 612px;
padding: 5px;
border: 2px dashed #444;
}
.wrapper > div{
display: -webkit-flex;
display: flex;
-webkit-flex-basis: 150px;
flex-basis: 150px;
justify-content: center;
align-items: center;
}
.aside-1, .aside-3{
background: #ccc
}
.aside-2{
background: #0ff;
}
<div class="wrapper">
<div class="aside aside-1">text1</div>
<div class="aside aside-2">text2</div>
<div class="aside aside-3">text3</div>
</div>
Flexbox to the rescue!
Good resources:
https://philipwalton.github.io/solved-by-flexbox/
https://github.com/philipwalton/flexbugs
#container {
display: flex; /* magic maker */
justify-content: space-between; /* set equal space between boxes */
border: 2px dashed #444;
height: 125px;
/* just for demo */
min-width: 612px;
}
.box1, .box2, .box3, .box4 {
display: flex; /* magic maker */
/*
shorthand for flex-grow, flex-shrink, and flex-basis properties
we don't want the boxes to grow or shrink, and the basis is the explicit
width we want them
*/
flex: 0 0 150px;
justify-content: center; /* horizontally center text within */
align-items: center; /* vertically center text within */
height: 125px;
}
.box1, .box3 {
background: #ccc
}
.box2, .box4 {
background: #0ff
}
<div id="container">
<div class="box1">Text</div>
<div class="box2">Text</div>
<div class="box3">Text</div>
</div>
you can use display:table/table-cell and using a workaround with border-collapse/spacing + margin you will get the desired output.
#wrap {
border: 2px dashed #444;
height: 125px;
text-align: justify;
-ms-text-justify: distribute-all-lines;
text-justify: distribute-all-lines;
overflow:hidden;
/* just for demo */
width: 612px;
}
#container {
margin: 0 -81px; /*must be equal to border-spacing */
}
#table {
display: table;
table-layout: fixed;
border-collapse: separate;
border-spacing: 81px 0;
width: 100%;
}
.box1,
.box2,
.box3,
.box4 {
width: 150px;
height: 125px;
vertical-align: middle;
display: table-cell;
text-align: center;
}
.stretch {
width: 100%;
vertical-align: middle;
display: table-cell;
}
.box1,
.box3 {
background: #ccc
}
.box2,
.box4 {
background: #0ff
}
<div id="wrap">
<div id="container">
<div id="table">
<div class="box1">Text</div>
<div class="box2">Text</div>
<div class="box3">Text</div>
<span class="stretch"></span>
</div>
</div>
</div>
Are you familiar with Bootstrap?
It is a CSS Framework made by Twitter.
Put this inside of your head -
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
Use this in your body to see what it does, there's great docs on it.
<div class="container"> <!-- Creates margin -->
<div class="row"> <!-- Read docs on rows, they're awesome! -->
<div class="col-lg-4"> <!-- 1 -->
<!-- Just to take up space -->
</div>
<div class="col-lg-4"> <!-- 2 -->
<!-- YOUR CONTENT GOES HERE -->
</div>
<div class="col-lg-4"> <!-- 3 -->
<!-- Just to take up space -->
</div>
</div> <!-- ./row -->
</div> <!-- ./container -->
Now inside of the 2nd ./col-lg-4 div all of that content will be perfectly centered in the screen with the text aligned left.
If you want to align center the text, replace
<div class="col-lg-4"> <!-- 2 -->
with
<div class="col-lg-4 text-center"> <!-- 2 -->
Hope this helps!

Resources