CSS flex grow does not work with added div on top - html

Consider the following fiddle: https://jsfiddle.net/7naxprzd/1/
Requirements are:
two columns with header and contents
tops of columns should align
bottom of columns should align
on top of each column there should be a horizontally centered arrow
The code is working properly if the arrows are eliminated by deleting the div with class .arrow-wrapper, but I need the arrows.
A solution could be to absolute position the arrow, but is there a way to solve this layout issue with flex without absolute positioning the arrow?
Should work for modern browsers and IE11.
.row-wrapper {
display: flex;
}
.col-wrapper-outer {
display: flex;
flex-wrap: wrap;
}
.arrow-wrapper {
width: 100%;
text-align: center;
font-size: 30px;
}
.col-wrapper {
width: 100%;
display: flex;
flex-direction: column;
border: 2px solid red;
color: white;
}
.col-wrapper .header {
background: blue;
}
.col-wrapper .contents {
flex: 1 0 auto;
background: green;
}
<div class="row-wrapper">
<div class="col-wrapper-outer">
<div class="arrow-wrapper">
↓
</div>
<div class="col-wrapper">
<div class="header">Please align tops.</div>
<div class="contents">Let me grow.</div>
</div>
</div>
<div class="col-wrapper-outer">
<div class="arrow-wrapper">
↓
</div>
<div class="col-wrapper">
<div class="header">please align tops.</div>
<div class="contents">Let me grow.<br>Please<br>align<br>bottoms.</div>
</div>
</div>
</div>

In your div with class col-wrapper-outer, instead of this:
.col-wrapper-outer {
display: flex;
flex-wrap: wrap;
}
Use this:
.col-wrapper-outer {
display: flex;
flex-direction: column;
}
Then add flex: 1 to .col-wrapper so it takes the full height of the container.
revised fiddle
.row-wrapper {
display: flex;
}
.col-wrapper-outer {
display: flex;
/* flex-wrap: wrap; */
flex-direction: column; /* NEW */
}
.arrow-wrapper {
width: 100%;
text-align: center;
font-size: 30px;
}
.col-wrapper {
flex: 1; /* NEW */
width: 100%;
display: flex;
flex-direction: column;
border: 2px solid red;
color: white;
}
.col-wrapper .header {
background: blue;
}
.col-wrapper .contents {
flex: 1 0 auto;
background: green;
}
<div class="row-wrapper">
<div class="col-wrapper-outer">
<div class="arrow-wrapper">
↓
</div>
<div class="col-wrapper">
<div class="header">Please align tops.</div>
<div class="contents">Let me grow.</div>
</div>
</div>
<div class="col-wrapper-outer">
<div class="arrow-wrapper">
↓
</div>
<div class="col-wrapper">
<div class="header">please align tops.</div>
<div class="contents">Let me grow.
<br>Please
<br>align
<br>bottoms.</div>
</div>
</div>
</div>

Related

Flex basis shrinks element but not parent

I am dealing with a flex-box issue. It seems that a flex item with flex basis is shrunk accordingly but the parent maintains its size as if the child still occupied its full size.
These two images are the exact same code except the .earnings-claim-wrapper in the second one does not have the flex property. The last image shows how chrome "represents" that empty space.
Expected behaviour:
I've reduced the code to this:
div{
padding:10px;
}
.earnings-container {
display: flex;
background-color: red;
}
.earnings-info-container {
background-color: orange;
}
.earnings-info {
display: flex;
flex-wrap: wrap;
justify-content: left;
align-items: flex-start;
background-color: green;
}
.earnings-info .earnings-claim {
align-self: flex-start;
background-color: yellow;
}
.earnings-claim-wrapper {
flex: 0 1 100px;
position: relative;
display: flex;
display: flex;
flex-direction: column;
background-color: purple;
}
<div class="earnings-container">
<div class="earnings-info-container">
<div class="earnings-info">
<div class="earnings-icon student-points"></div>
<div class="earnings-title">earnings-title</div>
<div class="earnings-claim-wrapper">
<div class="earnings-claim not-enough-effort">earnings-claim</div>
<span class="effort-message">Some long text text text text text text long text</span>
</div>
</div>
</div>
<div class="earnings-info-container">
<div class="earnings-info">
<div class="earnings-icon diamonds"></div>
<div class="earnings-title">earnings-title</div>
</div>
</div>
</div>
Instead of using flex: 0 1 100px; on earnings-claim-wrapper class, use width:100px;
div{
padding:10px;
}
.earnings-container {
display: flex;
background-color: red;
}
.earnings-info-container {
background-color: orange;
}
.earnings-info {
display: flex;
flex-wrap: wrap;
justify-content: left;
align-items: flex-start;
background-color: green;
}
.earnings-info .earnings-claim {
align-self: flex-start;
background-color: yellow;
}
.earnings-claim-wrapper {
width:100px;
position: relative;
display: flex;
display: flex;
flex-direction: column;
background-color: purple;
}
<div class="earnings-container">
<div class="earnings-info-container">
<div class="earnings-info">
<div class="earnings-icon student-points"></div>
<div class="earnings-title">earnings-title</div>
<div class="earnings-claim-wrapper">
<div class="earnings-claim not-enough-effort">earnings-claim</div>
<span class="effort-message">Some long text text text text text text long text</span>
</div>
</div>
</div>
<div class="earnings-info-container">
<div class="earnings-info">
<div class="earnings-icon diamonds"></div>
<div class="earnings-title">earnings-title</div>
</div>
</div>
</div>
I've got to be honest that I can't fully reproduce what happens in your code that makes .earning-info expand. But I did find out it has to do with setting a flex-basis on the .earnings-claim-wrapper elements.
Giving all it's parents a flex-basis as well did the trick here.
Also, I think you can remove some properties, I've commented them out in the snippet.
div{
padding:10px;
}
.earnings-container {
display: flex;
background-color: red;
}
.earnings-info-container {
flex: 0 1 1%;
background-color: orange;
display: flex;
align-items: flex-start;
}
.earnings-info {
flex: 0 1 1%;
display: flex;
/*flex-wrap: wrap;*/
/*justify-content: left;*/
/*align-items: flex-start;*/
background-color: green;
}
.earnings-info .earnings-claim {
/*align-self: flex-start;*/
background-color: yellow;
}
.earnings-claim-wrapper {
flex: 0 1 100px;
/*position: relative;
display: flex;*/
display: flex;
flex-direction: column;
background-color: purple;
}
<div class="earnings-container">
<div class="earnings-info-container">
<div class="earnings-info">
<div class="earnings-icon student-points">x</div>
<div class="earnings-title">earnings-title</div>
<div class="earnings-claim-wrapper">
<div class="earnings-claim not-enough-effort">earnings-claim</div>
<span class="effort-message">Some long text text text text text text long text</span>
</div>
</div>
</div>
<div class="earnings-info-container">
<div class="earnings-info">
<div class="earnings-icon diamonds">x</div>
<div class="earnings-title">earnings-title</div>
</div>
</div>
</div>

Trying to modify the width of the columns in this flexbox

I am trying to render rows with the date on the left and some text on the right.
I cant seem to work out how I changed the widths of the columns though?
Currently my day and text column are the same width.
I'd like to have the day as 50px and the text as 300px.
Is it possible with this code?
.sb-flex-row {
flex-direction: row;
display: flex;
}
.sb-flex-column {
flex-direction: column;
display: flex;
}
.sb-flex-body {
display: flex;
}
.sb-flex-body div:not([class*="flex"]) {
border: 1px solid white;
flex: 1 1 50px;
width: 200px;
}
<div class="sb-flex-body">
<div class="sb-flex-row">
<div style="background: #0980cc;">day</div>
</div>
<div class="sb-flex-column">
<div style="background: #09cc69;">month</div>
<div style="background: #cc092f;">year</div>
</div>
<div class="sb-flex-row">
<div style="background: #0980cc;">text</div>
</div>
</div>
I cleaned up and make it maybe simpler for you to understand. You have an outer wrapper that is flexible. The default direction is row and that is ok. Then you have two blocks. one block dateBlock and the second is a text block. the dateblock contains two blocks (a,b). and b you can assign the direction to the column. Afterward, you can assign the width to the text block and Dateblock. That is it :-)
.wrapper {
display: flex;
gap:10px;
}
.dateBlock {
display: flex;
background: yellow;
gap: 20px;
padding: 10px;
box-sizing: border-box;
}
.textBlock {
background: green;
padding: 10px;
box-sizing: border-box;
width: 300px;
}
.monthYear {
display: flex;
flex-direction: column;
width:50px;
}
.day {
font-size: 30px;
width: 50px;
}
<div class="wrapper">
<div class="dateBlock">
<div class="day">day</div>
<div class="monthYear">
<div>month</div>
<div>year</div>
</div>
</div>
<div class="textBlock">text</div>
</div>
I rearranged your markup a bit to easily target these divs in the style sheet. You can see the changes I made to your CSS under /* changes */. Also, take note of the HTML I adjusted.
.sb-flex-row {
flex-direction: row;
display: flex;
}
.sb-flex-column {
flex-direction: column;
display: flex;
}
.sb-flex-body {
display: flex;
}
/* changes */
.sb-flex-body div:not([class*="flex"]) {
border: 1px solid white;
width: 50px;
}
.sb-flex-row > div {
min-width: 300px;
}
<div class="sb-flex-body">
<div class="sb-flex-column">
<div style="background: #0980cc;">day</div>
<div style="background: #09cc69;">month</div>
<div style="background: #cc092f;">year</div>
</div>
<div class="sb-flex-row">
<div style="background: #0980cc;">text</div>
</div>
</div>

Trying to left-align text in a centered element

I am trying to achieve what you see at the bottom of the panel in the image below. Each of the 3 items are centered but the text is left aligned.
I have developed the following basic CSS and HTML code. I am trying to use flexbox as much as possible for responsive layout. Anyone have any pure HTML/CSS solution?
I understand that the p tag is a block level element. So what are my options without setting the width of the p tag? Or maybe there is another tag I could use?
The HTML and CSS code I have provided below has the basic structure only.
.panel {
display: flex;
border: 1px solid black;
min-height: 300px;
flex-direction: column;
max-width: 500px;
}
.panel-body {
display: flex;
flex: 1;
flex-flow: row wrap;
justify-content: center;
}
.panel-heading {
padding: 10px 10px;
}
.panel-body div.chart {
flex: 0 0 100%;
min-height: 150px;
background-color: green;
}
.panel-body div {
text-align: center;
flex: auto;
background-color: red;
display: flex;
flex-direction: column;
justify-content: space-around;
}
p {
border: 0;
padding: 0;
margin: 0;
text-align: left;
}
<div class="panel">
<div class="panel-heading">
HEADING
</div>
<div class="panel-body">
<div class="chart"></div>
<div>
<p>HIGH
<br/>144</p>
</div>
<div>MEDIUM
<br/>2</div>
<div>LOW
<br/>3</div>
</div>
</div>
Just changed styles of .panel-body div. Also there is no need for p tag here, consider removing it from markup. Demo:
.panel {
display: flex;
border: 1px solid black;
min-height: 300px;
flex-direction: column;
max-width: 500px;
}
.panel-body {
display: flex;
flex: 1;
flex-flow: row wrap;
justify-content: center;
}
.panel-heading {
padding: 10px 10px;
}
.panel-body div.chart {
flex: 0 0 100%;
min-height: 150px;
background-color: green;
}
.panel-body div {
/* Take 33.33% width, allow grow and shrink */
flex: 1 1 33.33%;
background-color: red;
/* become a flex-container */
display: flex;
/* align flex-items vertically */
flex-direction: column;
/* center vertically */
justify-content: center;
/* center horizontally */
align-items: center;
}
p {
border: 0;
padding: 0;
margin: 0;
text-align: left;
}
<div class="panel">
<div class="panel-heading">
HEADING
</div>
<div class="panel-body">
<div class="chart"></div>
<div>
<p>HIGH
<br/>144</p>
</div>
<div>MEDIUM
<br/>2</div>
<div>LOW
<br/>3</div>
</div>
</div>
Try this HTML code:
<div class="panel">
<div class="panel-heading">
HEADING
</div>
<div class="panel-body">
<div class="chart"></div>
<div><p>HIGH<br/>144</p></div>
<div><p>MEDIUM<br/>2</p></div>
<div><p>LOW<br/>3</p></div>
</div>
</div>
It appears that you originally only put the div containing "HIGH" and "144" in a <p> tag, which, according to your css code, is the attribute that is being styled to have left-aligned text. However, the content within the other 2 <div>s were not enclosed within a <p> tag, and so they were not being styled.

Use flexbox to center content while not making elements side by side

I am using flexbox to center content with justify-content: center which works as intended but flexbox also moves divs to be side by side which I don't want.
Here is an example
.flex {
display: flex;
justify-content: center;
}
.content {
width: 100px;
height: 100px;
background-color: #000;
margin: 10px;
}
<div class="flex">
<div class="content">
</div>
<div class="content">
</div>
</div>
How can I use flexbox while retaining the default one div on top of the other positioning.
You can set flex-direction: column and then you have to use align-items: center. Default flex-direction is row.
.flex {
display: flex;
align-items: center;
flex-direction: column;
}
.content {
width: 100px;
height 100px;
color: #000;
border: 1px solid black;
padding: 5px;
margin: 5px;
}
<div class="flex">
<div class="content"></div>
<div class="content"></div>
</div>
Try following code,
.flex {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.content {
width: 100px;
height: 100px;
background-color: #000;
margin: 10px;
}
<div class="flex">
<div class="content">
</div>
<div class="content">
</div>
</div>

Can you make flexbox background height the same?

I am using flexbox display and it is working fine. Except when I happen to use a background color on one of the divs, the color does not cover the entire height of the div. It ends up looking like this --
Of course what I'd like is for the background color to extend to the same height as the div to the right. Is this even possible with flexbox?
.row {
display: flex;
align-items: center;
}
.left {
flex: 1 0 auto;
background-color: wheat;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">Some text</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
The problem is that you use
align-items: center;
The default value does what you want:
align-items: stretch;
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
But then you will need to center the contents vertically. You can do it with more flexbox. Some examples:
Row layout and align-items:
.left {
display: flex; /* More flexbox */
align-items: center; /* Center in the cross (vertical) axis */
}
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
display: flex;
align-items: center;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
Column layout and justify-content:
.left {
display: flex; /* More flexbox */
flex-direction: column; /* Column layout */
justify-content: center; /* Center in the main (vertical) axis */
}
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
display: flex;
flex-direction: column;
justify-content: center;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>
Inserting pseudo-elements with auto margins:
.left {
display: flex; /* More flexbox */
flex-direction: column; /* Column layout */
}
.left::before, .left::after {
content: ''; /* Generate pseudo-elements */
margin: auto; /* Push contents */
}
.row {
display: flex;
}
.left {
flex: 1 0 auto;
background-color: wheat;
display: flex;
flex-direction: column;
}
.left::before, .left::after {
content: '';
margin: auto;
}
.right {
flex: 1 0 auto;
}
<div class="row">
<div class="left">
Some text
</div>
<div class="right">
<input type="text" style="height:40px" />
</div>
</div>