Stacked flexbox vertical centering not working in chrome - css

The following situation doesn't work in Google Chrome;
<div class="flex-container">
<div class="flex-item">
<div>
<div>
<h2>This is a test</h2>
</div>
</div>
</div>
<div class="flex-item">
<div>
<div>
<h2>This is a test</h2>
</div>
</div>
</div>
<div class="flex-item">
<div>
<div>
<h2>This is a test</h2>
</div>
</div>
</div>
</div>
SCSS
body,html {
height:100%;
background:#1D1F20;
font-family:sans-serif;
color:#fff;
}
.flex-container {
display: flex;
flex-direction: column;
align-items: center;
height:100%;
.flex-item {
flex: 1 1 auto;
align-self: center;
background:#87BEB7;
padding:0 10px;
&:nth-child(2) {
background:#ADBEBC;
}
&:nth-child(3) {
background:#BE8A74;
}
> div {
display: flex;
justify-content: center;
align-items: flex-start;
height:100%; // This seems to be the issue
div {
flex: 0 1 auto;
align-self: center;
background:#5C726F;
padding:10px
}
}
}
}
I would expect the second flexbox-container (.flex-item > div) to be the full height of the flex-child (.flex-item) but it doesn't seem to work. (chrome only)
The workaround I have involves using position absolute, but i'd rather not use it.
Codepen: http://codepen.io/anon/pen/QwpzLX
Open in Firefox to see the desired result and in Chrome to see the current situation.
Any help or suggestions would be appreciated.

Here is the working scss:
.flex-container {
display: flex;
flex-direction: column;
align-items: center;
height:100%;
.flex-item {
flex: 1 1 auto;
align-self: center;
background:#87BEB7;
padding:0 10px;
display: flex;
&:nth-child(2) {
background:#ADBEBC;
}
&:nth-child(3) {
background:#BE8A74;
}
> div {
display: flex;
justify-content: center;
align-items: flex-start;
div {
flex: 0 1 auto;
align-self: center;
background:#5C726F;
padding:10px
}
}
}
}
You have to set display:flex; to .flex-item and remove the height: 100%.
Here is the demo: http://jsfiddle.net/omgL91r8/1/

Related

CSS flexbox and justify-content [duplicate]

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>

How to make square divs shrink instead of hide when resizing screen?

I have a collection of a couple of divs (called buttons) inside a div container.
When attempting to resize the screen to check for responsiveness, (trying to keep them centered in the middle of the screen) instead of shrinking, the buttons FIRST get clipped from (or hide behind) both sides of the screen.
here is my code:
.button {
outline: 1px solid black;
min-width: 0;
min-height: 0;
width: 10rem;
height: 10rem;
flex: 1 0 1rem;
}
.container {
display: flex;
align-items: center;
justify-content: center;
}
.parentContainer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
Below are the global styles:
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
display: flex;
justify-content: center;
}
The html is made using components:
<div className={parentContainer}>
<div className={container}>
<HeaderButton />
<HeaderButton />
<HeaderButton />
<HeaderButton />
<HeaderButton />
<HeaderButton />
</div>
</div>
The header button component:
const Button = () => {
return (
<div className={button}>
<h1>{props.text}</h1>
</div>
)
}
export default Button;
Any idea how I might achieve what I'm aiming for?
Thank you for the help.
That's most probably due to the buttons having fixed width.
I'd suggest adding a responsive variant for the .container
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#media only screen and (min-width: 600px) {
.container {
flex-direction: row;
}
}
This will make the buttons fall one below the other.
Please use flex-wrap: wrap
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.item {
width: 100px;
height: 50px;
margin: 5px;
background: #000000;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Use display flex for responsiveness and percentages for element widths:
body{
width:100%;
height: 100vh;
display:flex;
justify-content: center;
align-items: center;
}
.container{
width:100%;
height:100px;
display:flex;
justify-content: center;
align-items: center;
flex-direction: row;
flex-wrap: wrap;
}
.d1,.d2,.d3,.d4,.d5{
width:100px;
height:100px;
border:2px solid black;
}
<div class="container">
<div class="d1"></div>
<div class="d2"></div>
<div class="d3"></div>
<div class="d4"></div>
<div class="d5"></div>
</div>
Ok so first I'd like to thank everyone for their responses, but the solution that I needed was in fact aspect-ratio:
.button {
width: 80%;
aspect-ratio: 1 / 1;
}
.container {
display: flex;
align-items: center;
justify-content: center;
margin-top: 5%;
width: 90vw;
gap: 3.5%;
}

How to make flexbox child not create horizontal scrolling

The scenario here is that I am importing a React header component that uses Flexbox onto a page that is wrapped in a lot of Flexbox css. I only have have access to myDiv (and can create as many divs as I want wrapped around it), but I am struggling with getting the header component to either truncate or wrap onto multiple lines.
My problems are solved if I specify a specific width of the page in pixels, but is there some way to tell the header component not to expand outside the space it is given? This also needs to work in IE11.
Would love some tips on how to debug this scenario. Thanks!
.myDiv { // Can edit this class
}
.outerContainer3 { // Cannot edit this class
margin-top: 0;
flex-direction: column;
flex: 1 0 auto;
display: flex;
}
.outerContainer2 { // Cannot edit this class
flex: 1 0 auto;
display: flex;
flex-direction: row;
}
.outerContainer1 { // Cannot edit this class
position: relative;
flex: 1 1 auto;
}
.headerContainer2 { // Cannot edit this class
align-items: center;
display: flex;
justify-content: space-between;
}
.headerContainer1 { // Cannot edit this class
min-width: 0%;
flex-shrink: 1;
width: 100%;
}
.header { // Cannot edit this class
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
<div class="outerContainer3">
<div class="outerContainer2">
<div class="outerContainer1">
<div>
<div>
<div class="myDiv">
<div class="headerContainer2">
<div class="headerContainer1">
<h1 class="header">asdfkasdjlfkasdjfla sjdlfkja sldkfj alskfj lskdjf laskdjf laskjf akjf lsakfjs lak jfkjflakj flkajds lakj f</h1>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
If you're able to add some css, then this one could help you.
Update:
I've added the 'position: absolute;' to the rule in this way the h1 element is not expanding out of the div element and it's working in the IE.
Also you're possibly interested in the property 'word-wrap' with the value 'break-word'. This should help you to wrap the very very long words(or urls) without the white-space.
.myDiv { // Can edit this class
}
.myDiv > div > div > h1 {
white-space: inherit;
position: absolute;
}
.outerContainer3 { // Cannot edit this class
margin-top: 0;
flex-direction: column;
flex: 1 0 auto;
display: flex;
}
.outerContainer2 { // Cannot edit this class
flex: 1 0 auto;
display: flex;
flex-direction: row;
}
.outerContainer1 { // Cannot edit this class
position: relative;
flex: 1 1 auto;
}
.headerContainer2 { // Cannot edit this class
align-items: center;
display: flex;
justify-content: space-between;
}
.headerContainer1 { // Cannot edit this class
min-width: 0%;
flex-shrink: 1;
width: 100%;
}
.header { // Cannot edit this class
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
<div class="outerContainer3">
<div class="outerContainer2">
<div class="outerContainer1">
<div>
<div>
<div class="myDiv">
<div class="headerContainer2">
<div class="headerContainer1">
<h1 class="header">asdfkasdjlfkasdjfla sjdlfkja sldkfj alskfj lskdjf laskdjf laskjf akjf lsakfjs lak jfkjflakj flkajds lakj f</h1>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Add a max width to outerContainer1 and to the myDiv elements.
.myDiv {
max-width: 100%;
}
.outerContainer3 {
margin-top: 0;
flex-direction: column;
flex: 1 0 auto;
display: flex;
}
.outerContainer2 {
flex: 1 0 auto;
display: flex;
flex-direction: row;
}
.outerContainer1 {
position: relative;
flex: 1 1 auto;
max-width: 100%;
}
.headerContainer2 {
align-items: center;
display: flex;
justify-content: space-between;
}
.headerContainer1 {
min-width: 0%;
flex-shrink: 1;
width: 100%;
}
.header {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
<div class="outerContainer3">
<div class="outerContainer2">
<div class="outerContainer1">
<div>
<div>
<div class="myDiv">
<div class="headerContainer2">
<div class="headerContainer1">
<h1 class="header">asdfkasdjlfkasdjfla sjdlfkja sldkfj alskfj lskdjf laskdjf laskjf akjf lsakfjs lak jfkjflakj flkajds lakj f</h1>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

force last div on a new line with flexbox [duplicate]

This question already has answers here:
Force flex item to span full row width
(2 answers)
Closed 5 years ago.
I have this HTML
<div class="wrap">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
<div class="four"></div>
</div>
plus this CSS
.wrap {
display: flex;
align-items: center;
}
.one {
flex: 0 1 200px;
}
.two {
display: flex;
flex: 1 1 auto;
align-items: center;
justify-content: center;
}
.three {
display: flex;
flex: 0 1 200px;
justify-content: flex-end;
}
.four {
???
}
and i wanna make it look like this, i don't know what else to use for .four to make that last div to move on a new line plus 100% width
[- one -----][----- two -----][----- three -]
[----------------- four --------------------]
atm looks like this
[- one -----][----- two -----][----- three -] [- four -----]
i know i can use another
<div class="wrap">
but i don't want this,
Thank you.
Add flex-wrap: wrap to the .wrap class, and make your .four class flex: 1 1 100%, that should do the trick:
.wrap {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.one {
flex: 0 1 200px;
}
.two {
display: flex;
flex: 1 1 auto;
align-items: center;
justify-content: center;
}
.three {
display: flex;
flex: 0 1 200px;
justify-content: flex-end;
}
.four {
flex: 1 1 100%;
}
Here's a Codepen example (I added a border and height to your divs just to make it easier to visualise).
Please check you can try this
<div class="wrap">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
<div class="four"></div>
</div>
CSS
.wrap {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
.wrap > div{
border: 1px solid;
height: 200px;
}
.one {
flex: 0 1 200px;
}
.two {
flex: 1 1 auto;
}
.three {
flex: 0 1 200px;
}
.four {
flex: 100%;
}
link https://jsfiddle.net/JentiDabhi/eoat01zn/
this is simple:
To achieve this:
.wrapper{
display: flex;
flex-wrap: wrap;
flex-direction: row;
background: blue;
width: 100%;
}
.one, .two, .three{
width: 33%;
background:red;
}
.four{
width:100%;
background:pink;
}
<div class="wrapper">
<div class="one">
one
</div>
<div class="two">
two
</div>
<div class="three">
three
</div>
<div class="four">
four
</div>
</div>

Use justify-content: flex-end and to have vertical scrollbar

I have chat and I need to scroll all content to bottom.
I want to use justify-content: flex-end and to have vertical scrollbar.
.session-textchat {
height: 320px;
background: #fff;
display: -webkit-flex;
display: flex;
-webkit-align-items: flex-end;
align-items: flex-end;
-webkit-justify-content: space-between;
justify-content: space-between;
-webkit-flex-direction: column;
flex-direction: column;
}
.session-textchat .past-messages {
width: 100%;
max-width: 980px;
margin: 0 auto;
height: 83.92%;
overflow-y: auto;
padding: 30px 0 0;
display: -webkit-flex;
display: flex;
-webkit-align-items: flex-end;
align-items: flex-end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
-webkit-flex-direction: column;
flex-direction: column;
}
.session-textchat .past-messages .receiver,
.session-textchat .past-messages .sender {
width: 100%;
min-height: 47px;
margin: 0 0 20px;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: row;
flex-direction: row;
}
.session-textchat .past-messages .receiver .message,
.session-textchat .past-messages .sender .message {
position: relative;
padding: 17px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.session-textchat .past-messages .receiver {
text-align: left;
-webkit-justify-content: flex-start;
justify-content: flex-start;
}
.session-textchat .past-messages .receiver .message {
background: #f4f4f4;
color: #535353;
}
.session-textchat .past-messages .sender {
text-align: right;
-webkit-justify-content: flex-end;
justify-content: flex-end;
}
.session-textchat .past-messages .sender .message {
background: url('../img/rgbapng/0050ff26.png');
background: rgba(0, 80, 255, 0.15);
color: #0050ff;
}
<div class="session-textchat">
<div class="past-messages">
<div class="receiver">
<span class="message">
Good afternoon David. Welcome to your appointment! How are you today?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
</div>
</div>
Example is here.
Is it possible?
Or please give me better solution.
Thanks in advance!
Srdjan
I just had to face this issue myself and, after concluding it is a bug, I came up with a workaround.
In summary, don't use justify-content: flex-end but rather put a margin-top: auto on the first child. Unlike flex-end this doesn't break the scrollbar functionality, and it bottom-aligns the contents when they're not overflowing the container.
Example based on #SrdjanDejanovic's fiddle is at https://jsfiddle.net/peter9477/4t5r0t5b/
In case the example isn't available, here's the relevant CSS:
#container {
overflow-y: auto;
display: flex;
flex-flow: column nowrap;
/* justify-content: flex-end; DO NOT USE: breaks scrolling */
}
#container > :first-child {
margin-top: auto !important;
/* use !important to prevent breakage from child margin settings */
}
An alternative workaround that I believe I've also used is to add an extra container for the scrollbar. Use the flex-end on the inner container and have the outer container handle the scrolling. I generally dislike workarounds that require adding dummy elements though, so I prefer my CSS-only solution above.
Probably you've already solved this, but I faced this problem too and found a solution by trial and error, so I'm going to share it.
Having parent container's display set to flex display: flex and child's items align to flex-end align-items: flex-end will prevent overflow-y: auto to work.
Instead, you can leave you can use next CSS properties for your parent container (in your case session-textchat):
display: flex;
flex-direction: column-reverse; /* 'column' for start, 'column-reverse' for end */
overflow-y: scroll; /* or overflow-y: auto ... */
This will make your child div appear on the bottom of parent container (it will act like flex-end) and enable vertical scroll if content height is bigger than parent container.
I made a little jsfiddle for you if this sounds confusing:
https://jsfiddle.net/lbartolic/9od4nruy/3/
In jsfiddle you can see header part, content part and footer. Container has fixed height and each part takes required height to fill the container. Content part _b__content will be scrollable if its content is taller than _b__content's height.
I hope this will help someone.
Cheers.
Also There is also another Solution
Remove the justify-content and add flex: 1 1 auto; property to the first element(create an empty div)
Old
HTML
<div class="content-reversed">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
CSS
.content-reversed {
display: flex;
flex-direction: column;
justify-content: flex-end;
}
New
HTML
<div class="content-reversed">
<div class="fix"></div> //add this dummy div
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
CSS
.content-reversed {
display: flex;
flex-direction: column;
}
.content-reversed .fix {
flex: 1 1 auto;
}
It seems to be a common bug among the browsers.
You should distribute your style onto 2 containers: the outer will be scrolled, and the inner will be a flex container. Also, you need some js to keep your message list scrolled to bottom while adding new messages.
Here is an example of code:
markup:
<div id='outer'>
<div id='inner-scroll'>
<div id='inner-flex'>
<div class='flex-item'>Item 1</div>
<div class='flex-item'>Item 2</div>
...
</div>
</div>
style:
#inner-scroll {
height: 100%;
overflow: auto;
}
#inner-flex {
display: flex;
flex-direction: column;
justify-content: flex-end;
min-height: 100%;
}
.flex-item { /*nothing*/ }
JS:
function messagePushCallback()
{
var scrollable=document.getElementById('inner-scroll');
scrollable.scrollTo(0, scrollable.scrollHeight-scrollable.clientHeight);
}
// for an example
chat.onMessagePush(messagePushCallback);
window.addEventListener('load', messagePushCallback);
In JS, scrollable.scrollHeight shows the whole height of the element, including the space beyond its visible part, while scrollable.clientHeight is for the height of the visible part.
You have to turn .session-textchat into a flex column then margin-top: auto on .past-messages to send it to the bottom. Then play with overflow-y: scroll and some jQuery:
function updateScroll() {
$("#chat").animate({ scrollTop: $('#chat').prop("scrollHeight")}, 1000);
}
updateScroll();
$("#send_button").on('click', updateScroll);
.session-textchat {
display: flex;
flex-direction: column;
height: 300px;
margin-bottom: 30px;
background: #fff;
overflow-y: scroll;
}
.session-textchat .past-messages {
margin-top: auto;
width: 100%;
max-width: 980px;
}
.session-textchat .past-messages .receiver,
.session-textchat .past-messages .sender {
width: 100%;
min-height: 47px;
margin: 0 0 20px 0;
}
.session-textchat .past-messages .receiver .message,
.session-textchat .past-messages .sender .message {
position: relative;
padding: 15px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.session-textchat .past-messages .receiver {
text-align: left;
}
.session-textchat .past-messages .receiver .message {
background: #f4f4f4;
color: #535353;
}
.session-textchat .past-messages .sender {
text-align: right;
}
.session-textchat .past-messages .sender .message {
background: url("../img/rgbapng/0050ff26.png");
background: rgba(0, 80, 255, 0.15);
color: #0050ff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div id="chat" class="session-textchat">
<div class="past-messages">
<div class="receiver">
<span class="message">
Good afternoon David. Welcome to your appointment! How are you today?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
<div class="sender">
<span class="message">
Hello doctor. I feel terrible to be honest.
</span>
</div>
<div class="receiver">
<span class="message">
I can see from your notes that you've been having some ear ache - can you tell me a bit more about your symptoms?
</span>
</div>
</div>
</div>
<div class="form-group">
<textarea class="form-control" rows="5" id="msg"></textarea>
</div>
<div class="form-group text-center">
<button href="#" id="send_button" class="btn btn-success">Send message</button>
</div>
</div>
Look at this full-screen jsFiddle.
This solution worked for me:
display: flex;
flex-direction: row-reverse;
justify-content: flex-start;

Resources