Expand multiple flexbox items to fit container width - css

I have a layout where I want to make the breadcrumb trail use up all of the available space in the row. In the same row I also have a div (.tools) which needs to be of a dynamic width as it's contents may vary.
At the moment I have to set the breadcrumb trail to a % width to get it to work roughly correctly, but this isn't ideal... I'd like it to just expand to fill the available space.
Any ideas?
header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
background-color: lightgreen;
width: 100%;
box-sizing: border-box;
}
.breadcrumb {
display: flex;
align-items: center;
justify-content: flex-start;
white-space: nowrap;
width: 55%;
background-color: lightblue;
}
.breadcrumbItem {
display: flex;
flex: 0 10 auto;
min-width: 45px;
align-items: center;
overflow: hidden;
text-overflow: ellipsis;
}
.breadcrumbItem button {
border: 0;
background: none;
padding: 0 5px;
flex: 0 1 auto;
white-space: nowrap;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
.tools {
display: flex;
justify-content: flex-end;
background-color: lightyellow;
}
.tools span, .tools button {
white-space: nowrap;
}
<header>
<div class="breadcrumb">
<div class="breadcrumbItem">
<button>Really long breadcrumb item here</button>
<span>
<span>></span>
</span>
</div>
<div class="breadcrumbItem">
<button>Another really long item that should ellipse when it gets too long, oidsf jsodifj dsoifj sdoifj sdoifj sdoifj sdoifj sdoifj sdoifj dsoifj sdoifj sd</button>
</div>
</div>
<div class="tools">
<span>0 photos selected</span>
<button>Button</button>
</div>
</header>
https://codepen.io/anon/pen/NYaQyV

You can use flex-grow: 1; or the shorthand flex: 1; along with min-width or overflow.
.breadcrumb {
...
flex: 1;
min-width: 0;
}
Or
.breadcrumb {
...
flex: 1;
overflow: hidden;
}
CodePen

you can achieve what you want with by adding flex: auto to the .breadcrumb selctor block. a lot of your css declarations are redundant. you need to look into them and group selectors having much declarations in common
header {
-webkit-display: flex;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
background-color: lightgreen;
width: 100%;
box-sizing: border-box;
}
.breadcrumb {
flex: auto; //note this line .you can change it to auto as well
display: flex;
align-items: center;
justify-content: flex-start;
white-space: nowrap;
background-color: lightblue;
}
.breadcrumbItem {
flex: auto;
min-width: 45px;
overflow: hidden;
text-overflow: ellipsis;
}

There's a lot of redundancy in your code. Here's a simplified version that may achieve your goals.
header {
display: flex;
padding: 16px 20px;
background-color: lightgreen;
}
.breadcrumb {
flex-grow: 1;
display: flex;
overflow: hidden;
background-color: lightblue;
}
.breadcrumbItem {
display: flex;
}
button {
border: 0;
background: none;
padding: 0 5px;
}
.breadcrumbItem:last-child {
overflow: hidden;
}
.breadcrumbItem:last-child button { /* ellipsis on second button only */
overflow: hidden;
text-overflow: ellipsis;
}
.tools {
margin-left: auto;
background-color: lightyellow;
}
* {
box-sizing: border-box;
white-space: nowrap;
}
<header>
<div class="breadcrumb">
<div class="breadcrumbItem">
<button>Really long breadcrumb item here</button>
<span>
<span>></span>
</span>
</div>
<div class="breadcrumbItem">
<button>Another really long item that should ellipse when it gets too long, oidsf jsodifj dsoifj sdoifj sdoifj sdoifj sdoifj sdoifj sdoifj dsoifj sdoifj sd</button>
</div>
</div>
<div class="tools">
<span>0 photos selected</span>
<button>Button</button>
</div>
</header>
revised codepen

Related

Why does text-overflow not function with a div in a grid?

I was trying to make my design responsive by making it so that when the screen gets smaller in width, the text should be 'cut off' by three dots. However, this does not seem to function in my situation, as the .container element just seems to overflow into the main element, instead of the text getting smaller. How could I fix this? Thanks in advance!
<main>
<div class="container">
<section class="account-section">
<h5 class="username">WWWWWWWWWWWWWWWWW</h5>
</section>
</div>
</main>
<style>
main {
height: 200px;
display: grid;
place-items: center;
padding: 50px;
}
.container {
position: relative;
display: grid;
grid-template: fit-content(100%) / 100%;
max-width: 1240px;
width: 100%;
position: relative;
}
.account-section {
height: fit-content;
background: var(--white);
box-shadow: 0 0 50px rgb(0, 0, 0, 0.15);
padding: 25px;
position: relative;
flex-shrink: 1;
}
.username {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
</style>
overflow in this context means, that the content cannot fit in the container and so overflows. Here the container is the <h5>, while the content is the text. The <h5> will just grow according to the text content by default, because it's not constrained, neither by rules set to itself nor by rules for the parent.
If you put a width: 20% on the <h5> as demonstrated below for example, the text would overflow, and the text-overflow: ellipsis kicks in.
Another option would be to add overflow: hidden to the parent with class .account-section
Just click on the Run code snippet button, and you'll see.
main {
height: 200px;
display: grid;
place-items: center;
padding: 50px;
}
.container {
position: relative;
display: grid;
grid-template: fit-content(100%) / 100%;
max-width: 1240px;
width: 100%;
position: relative;
}
.account-section {
height: fit-content;
background: var(--white);
box-shadow: 0 0 50px rgb(0, 0, 0, 0.15);
padding: 25px;
position: relative;
flex-shrink: 1;
overflow: hidden;
}
.username {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
width: 20%;
}
.username-fullwidth {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
<main>
<div class="container">
<section class="account-section">
<h5 class="username">WWWWWWWWWWWWWWWWW</h5>
</section>
</div>
<div class="container">
<section class="account-section">
<h5 class="username-fullwidth">WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWw</h5>
</section>
</div>
</main>

How to let a Flex column on the bottom keeping the items order using CSS? [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.
I have a horizontally centered column of Flex items ordered from 1 to 5 that are aligned from the top of the container like this:
body, html {
height: 100%;
position: relative;
margin: 0;
padding: 0;
}
.container {
display: inline-flex;
flex-wrap: wrap;
flex-direction: column;
align-items: flex-end;
align-content: center;
width: 100%;
height: 100%;
background: pink;
}
.item {
margin: 1px;
width: 30px;
height: 30px;
background: green;
}
<div class=container><div class=item>1</div><div class=item>2</div><div class=item>3</div><div class=item>4</div><div class=item>5</div></div>
I would like to let it aligned by the bottom of the container instead. I manage to do it with flex-direction: column-reverse; like in the next Snippet:
body, html {
height: 100%;
position: relative;
margin: 0;
padding: 0;
}
.container {
display: inline-flex;
flex-wrap: wrap;
flex-direction: column-reverse;
align-items: flex-end;
align-content: center;
width: 100%;
height: 100%;
background: pink;
}
.item {
margin: 1px;
width: 30px;
height: 30px;
background: green;
}
<div class=container><div class=item>1</div><div class=item>2</div><div class=item>3</div><div class=item>4</div><div class=item>5</div></div>
However, as you see, the items get out of order! Is there a way to let a flex column on the bottom without reversing the items order using CSS? I tried every Flex property that I know so far without success.
You can use justify-content: end;
.container {
width: 150px;
height: 150px;
border: 1px solid black;
display: flex;
flex-direction: column;
align-items: center;
justify-content: end;
}
.content {
width: 25px;
height: 25px;
border: 1px solid black;
}
<div class="container">
<div class="content">1</div>
<div class="content">2</div>
<div class="content">3</div>
<div class="content">4</div>
<div class="content">5</div>
</div>
You need to use the justify-content property to align content along the main axis (in your case vertically). You are using align-items which defines how the items should be aligned along the cross axis.
body, html {
height: 100%;
position: relative;
margin: 0;
padding: 0;
}
.container {
display: inline-flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: flex-end;
align-content: center;
width: 100%;
height: 100%;
background: pink;
}
.item {
margin: 1px;
width: 30px;
height: 30px;
background: green;
}
<div class=container>
<div class=item>1</div>
<div class=item>2</div>
<div class=item>3</div>
<div class=item>4</div>
<div class=item>5</div>
</div>

Restrict element height to content, and maintain collapsed overflow

I have a pop-up modal which works overall, however the one annoyance is it has a hardcoded max-height which I'd like to eliminate.
Option #1:
Initially I explored using height: auto on the modal, which does keep the modal height to the natural height of the contents. However this effects the collapsing of the modal when you scale the browser viewport to a short height. The modal overflows out of the viewport, instead of only the green image area overflowing.
Option #2: I'm aware of the possibility of max-content (for height... or even max-height ?) but I haven't been able to get it to work anywhere, and anyhow it has spotty browser support.
Option #3 (current): Setting the modal to height: 100% and max-height: 500px is good enough, however obviously the content needs to be shorter than that.
Overall, requirements are:
A - In small screens, the modal should collapse with the green image area overflowing, thereby maintaining modal title and buttons in view.
B - In large screens, the modal height should only be as big as the contents.
C - Whatever happens, the modal should never visibly go past the global padding (2em).
See #modal in CSS below:
Demo and code here (Codepen)
html, body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
#app {
background-color: gray;
width: 75%;
height: 75%;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
padding: 2em;
}
#container {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
#modal {
/* OPTION #1 */
/* FAILS in small screen: overflow of green image not invoked */
/* height: auto; */
/* OPTION #2 */
/* Not working? */
/* height: max-content; */
/* OPTION #3 */
/* WORKS but specifying a max-height is not ideal */
height: 100%;
max-height: 500px;
width: auto;
position: relative;
background-color: pink;
overflow: hidden;
}
#modal_inner {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
padding: 2em;
box-sizing: border-box;
}
#image {
overflow-y: auto;
overflow-x: hidden;
flex: 1;
}
#image .inner {
background-color: lime;
padding: 1em;
width: 400px;
height: 200px;
}
#controls {
background-color: yellow;
display: flex;
justify-content: center;
max-width: 20em;
width: 100%;
padding: 1em;
margin-top: 1em;
}
#cta {
background-color: white;
display: flex;
justify-content: center;
max-width: 10em;
padding: 1em;
margin-top: 1em;
}
<div id="app">
<div id="container">
<div id="modal">
<div id="modal_inner">
<div id="title">TITLE</div>
<div id="image">
<div class="inner">image</div>
</div>
<div id="controls">controls</div>
<div id="cta">submit</div>
</div>
</div>
</div>
</div>
You are almost good, use max-height:100% and also add display:flex that will give the height:100% effect you are trying to achieve on the modal_inner
html, body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
#app {
background-color: gray;
width: 75%;
height: 75%;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
padding: 2em;
}
#container {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
#modal {
max-height: 100%;
display:flex;
position: relative;
background-color: pink;
overflow: hidden;
}
#modal_inner {
display: flex;
flex-direction: column;
align-items: center;
/*height: 100%; remove this*/
padding: 2em;
box-sizing: border-box;
}
#image {
overflow-y: auto;
overflow-x: hidden;
flex: 1;
}
#image .inner {
background-color: lime;
padding: 1em;
width: 400px;
height: 200px;
}
#controls {
background-color: yellow;
display: flex;
justify-content: center;
max-width: 20em;
width: 100%;
padding: 1em;
margin-top: 1em;
}
#cta {
background-color: white;
display: flex;
justify-content: center;
max-width: 10em;
padding: 1em;
margin-top: 1em;
}
<div id="app">
<div id="container">
<div id="modal">
<div id="modal_inner">
<div id="title">TITLE</div>
<div id="image">
<div class="inner">image</div>
</div>
<div id="controls">controls</div>
<div id="cta">submit</div>
</div>
</div>
</div>
</div>

Min-width does not work on nested flexbox

This code has min-width working.
.list-header {
display: flex;
width: 150px;
height: 80px;
background-color: #ececec;
}
.list-component {
display: flex;
flex: 1;
padding-left: 24px;
padding-right: 24px;
min-width: 0;
}
.header-container {
display: flex;
flex: 1;
min-width: 0;
}
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
min-width: 0;
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
<div class="list-header">
<div class="list-component">
<div class="header-container">
<div class="header-text">
<span>long long long long long long text</span>
</div>
</div>
</div>
</div>
However, if you set align-items: flex-start; to .header-text, min-width will not work. Here is the code.
.list-header {
display: flex;
width: 150px;
height: 80px;
background-color: #ececec;
}
.list-component {
display: flex;
flex: 1;
padding-left: 24px;
padding-right: 24px;
min-width: 0;
}
.header-container {
display: flex;
flex: 1;
min-width: 0;
}
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start; /* ADD THIS!! */
min-width: 0;
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
<div class="list-header">
<div class="list-component">
<div class="header-container">
<div class="header-text">
<span>long long long long long long text</span>
</div>
</div>
</div>
</div>
I thought that flex-direction had an effect and changedmin-width: 0;tomin-height: 0;, but it did not work out.
Also, I read the specification of this, but I could not do anything.
https://drafts.csswg.org/css-flexbox/#min-size-opt
https://drafts.csswg.org/css-flexbox/#align-items-property
I am the first time to see this phenomenon.
Why does this happen? Is there a solution?
Thank you.
The issue is not with min-width as you may think because if you add border you will see that all the elements aren't overflowing (due to min-width:0) and only the last span is overflowing
.list-header {
display: flex;
width: 150px;
height: 80px;
background-color: #ececec;
border:2px solid red;
}
.list-component {
display: flex;
flex: 1;
padding-left: 24px;
padding-right: 24px;
min-width: 0;
border:2px solid blue;
}
.header-container {
display: flex;
flex: 1;
min-width: 0;
border:2px solid green;
}
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
align-items:flex-start;
min-width: 0;
border:2px solid yellow;
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
border:2px solid;
}
<div class="list-header">
<div class="list-component">
<div class="header-container">
<div class="header-text">
<span>long long long long long long text</span>
</div>
</div>
</div>
</div>
So we can simplify your issue like follow:
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
min-width: 0;
border: 2px solid yellow;
width: 150px;
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
border: 2px solid;
}
<div class="header-text">
<span>long long long long long long text</span>
</div>
Why align-items break you code? Simply because the initial value was stretch which mean that you span will have its width to be stretched to fit the width of the flex container (like doing width:100%). By chaging the alignment you no more have this feature and you create the overflow.
To fix this you can simply use width:100% instead. The main idea is to have a property that will force the width to be full width of the parent element so that you limit the width of the element thus the ellipsis will work:
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
min-width: 0;
border: 2px solid yellow;
width: 150px;
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
border: 2px solid;
width:100%;
}
<div class="header-text">
<span>long long long long long long text</span>
</div>
And with your initial code:
.list-header {
display: flex;
width: 150px;
height: 80px;
background-color: #ececec;
border:2px solid red;
}
.list-component {
display: flex;
flex: 1;
padding-left: 24px;
padding-right: 24px;
min-width: 0;
border:2px solid blue;
}
.header-container {
display: flex;
flex: 1;
min-width: 0;
border:2px solid green;
}
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
align-items:flex-start;
min-width: 0;
border:2px solid yellow;
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
border:2px solid;
width:100%;
}
<div class="list-header">
<div class="list-component">
<div class="header-container">
<div class="header-text">
<span>long long long long long long text</span>
</div>
</div>
</div>
</div>
Add overflow:hidden to the .header-container div:
.list-header {
display: flex;
width: 150px;
height: 80px;
background-color: #ececec;
}
.list-component {
display: flex;
flex: 1;
padding-left: 24px;
padding-right: 24px;
min-width: 0;
}
.header-container {
display: flex;
flex: 1;
min-width: 0;
overflow: hidden;
}
.header-text {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start; /* ADD THIS!! */
min-width: 0;
}
span {
white-space: nowrap;
}
<div class="list-header">
<div class="list-component">
<div class="header-container">
<div class="header-text">
<span>long long long long long long text</span>
</div>
</div>
</div>
</div>

How to prevent parent expand by overflow hidden child text?

HTML:
<nav>
<span>
<h3>123</h3>
<h3>111111111111111111111111111111111111111111111111111111111111</h3>
</span>
</nav>
SCSS:
nav {
width: 100%;
display: flex;
justify-content: center;
span {
display: inline-flex;
align-items: center;
h3 {
overflow: hidden;
max-width: 30%;
text-overflow: ellipsis;
white-space: nowrap;
margin: 0 1em;
}
}
}
The code in here:
https://codepen.io/arkceajin/pen/bKNOwX
Could see an invisible area inside <span>, and it will expand if increase the text contents.
Expected result: make the <span> align centre in <nav>.
In your example span is a flex-container - so it should have justify-content: center if you want to center it's children along main axis.
nav {
width: 100%;
display: flex;
}
nav span {
display: inline-flex;
border: 1px solid blue;
justify-content: center;
}
nav span h3 {
border: 1px solid red;
overflow: hidden;
max-width: 30%;
text-overflow: ellipsis;
white-space: nowrap;
margin: 0 1em;
}
<nav>
<span>
<h3>123</h3>
<h3>111111111111111111111111111111111111111111111111111111111111</h3>
</span>
</nav>

Resources