Flexbox layout losing proportions when reduced in size - html

I'm reproducing a golden spiral using CSS flexbox and percentage size for cells.
The round shape is drawn using a regular border and border-radius combination.
Everything is proportional until I resize the window to smaller widths.
I tried removing borders completely and turns out the layout is still losing proportions at some point.
Big container:
Small container:
Demo:
https://jsfiddle.net/s09rkwub/1/
html
<div class="wrapper">
<div class="rows fib">
<div class="cols fill">
<div class="rows fill">
<div class="fr tl">3</div>
<div class="fill cols">
<div class="fc bl">4</div>
<div class="fill rows">
<div class="fill cols">
<div class="fill tl fr">7</div>
<div class="fc tr">6</div>
</div>
<div class="fr br">5</div>
</div>
</div>
</div>
<div class="fc tr">2</div>
</div>
<div class="fr br">1</div>
</div>
</div>
css
.rows {
flex-direction: column;
}
.cols {
flex-direction: row;
}
.rows,
.cols {
display: flex;
.fill {
flex: 1;
}
> * {
outline: solid 1px rgba(127,127,127, 0.3);
}
}
...
Update:
Working demo with applied solution.
Update 2
Thanks to Your support guys. I could finish my fib spiral codepen.

Solution
Add this to your code:
* {
flex-shrink: 0;
min-width: 0;
min-height: 0;
}
revised fiddle
Explanation
Two concepts to consider:
An initial setting of a flex container is flex-shrink: 1.
This means that, by default, flex items are allowed to shrink below any defined width, height or flex-basis.
To prevent this behavior use flex-shrink: 0.
More details here: What are the differences between flex-basis and width?
An initial setting of a flex item is min-width: auto.
This means that, by default, a flex item cannot be smaller than the size of its content (regardless of flex-shrink or flex-basis).
To allow flex items to shrink past their content use min-width: 0 (row direction), min-height: 0 (column direction), or overflow: hidden (other values also work, except visible).
More details here: Why doesn't flex item shrink past content size?
With the adjustment below, your flex items can shrink past the text you have in your divs, allowing the scaling to continue without any obstacles:
* {
flex-shrink: 0;
min-width: 0;
min-height: 0;
}

Taking <div class="fr br">5</div> as an example, it's min-width is 26px. Thus, scaling the spiral down to a level, where the mentioned div's height becomes less than 26px, it's getting distorted.
If you change the border width to 1px instead of 5px, you'll see, that suddenly, it's able to scale down to 18px perfectly fine and breaks in smaller sizes.
That's why you probably tried to reduce the border. However, the reason for the distortion is much simpler: You have content inside the divs and they do require some space (even if the font color is transparent). If you remove all the numbers from the div elements, you get the desired result. See the demo at https://jsfiddle.net/s09rkwub/2/

Related

Give text width priority over max-width divs while keeping wrapping behavior [duplicate]

I have 2 divs side-by-side in a flexbox. The right hand one should always be the same width, and I want the left hand one to just grab the remaining space. But it won't unless I specifically set its width.
So at the moment, it's set to 96% which looks OK until you really squash the screen - then the right hand div gets a bit starved of the space it needs.
I guess I could leave it as it is but it feels wrong - like there has to be a way to say:
the right one is always the same; you on the left - you get everything that's left
.ar-course-nav {
cursor: pointer;
padding: 8px 12px 8px 12px;
border-radius: 8px;
}
.ar-course-nav:hover {
background-color: rgba(0, 0, 0, 0.1);
}
<br/>
<br/>
<div class="ar-course-nav" style="display:flex; justify-content:space-between;">
<div style="width:96%;">
<div style="overflow:hidden; white-space:nowrap; text-overflow:ellipsis;">
<strong title="Course Name Which is Really Quite Long And Does Go On a Bit But Then When You Think it's Stopped it Keeps on Going for even longer!">
Course Name Which is Really Quite Long And Does Go On a Bit But Then When You Think it's Stopped it Keeps on Going for even longer!
</strong>
</div>
<div style="width:100%; display:flex; justify-content:space-between;">
<div style="color:#555555; margin-right:8px; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;" title="A really really really really really really really really really really really long department name">
A really really really really really really really really really really really long department name
</div>
<div style="color:#555555; text-align:right; white-space:nowrap;">
Created: 21 September 2016
</div>
</div>
</div>
<div style="margin-left:8px;">
<strong>></strong>
</div>
</div>
Use the flex-grow property to make a flex item consume free space on the main axis.
This property will expand the item as much as possible, adjusting the length to dynamic environments, such as screen re-sizing or the addition / removal of other items.
A common example is flex-grow: 1 or, using the shorthand property, flex: 1.
Hence, instead of width: 96% on your div, use flex: 1.
You wrote:
So at the moment, it's set to 96% which looks OK until you really squash the screen - then the right hand div gets a bit starved of the space it needs.
The squashing of the fixed-width div is related to another flex property: flex-shrink
By default, flex items are set to flex-shrink: 1 which enables them to shrink in order to prevent overflow of the container.
To disable this feature use flex-shrink: 0.
For more details see The flex-shrink factor section in the answer here:
What are the differences between flex-basis and width?
Learn more about flex alignment along the main axis here:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
Learn more about flex alignment along the cross axis here:
How does flex-wrap work with align-self, align-items and align-content?
Basically I was trying to get my code to have a middle section on a 'row' to auto-adjust to the content on both sides (in my case, a dotted line separator). Like #Michael_B suggested, the key is using display:flex on the row container and at least making sure your middle container on the row has a flex-grow value of at least 1 higher than the outer containers (if outer containers don't have any flex-grow properties applied, middle container only needs 1 for flex-grow).
Here's a pic of what I was trying to do and sample code for how I solved it.
.row {
background: lightgray;
height: 30px;
width: 100%;
display: flex;
align-items:flex-end;
margin-top:5px;
}
.left {
background:lightblue;
}
.separator{
flex-grow:1;
border-bottom:dotted 2px black;
}
.right {
background:coral;
}
<div class="row">
<div class="left">Left</div>
<div class="separator"></div>
<div class="right">Right With Text</div>
</div>
<div class="row">
<div class="left">Left With More Text</div>
<div class="separator"></div>
<div class="right">Right</div>
</div>
<div class="row">
<div class="left">Left With Text</div>
<div class="separator"></div>
<div class="right">Right With More Text</div>
</div>

How to separate two text with dotted line horizontally ie: text1...........text2 [duplicate]

I have 2 divs side-by-side in a flexbox. The right hand one should always be the same width, and I want the left hand one to just grab the remaining space. But it won't unless I specifically set its width.
So at the moment, it's set to 96% which looks OK until you really squash the screen - then the right hand div gets a bit starved of the space it needs.
I guess I could leave it as it is but it feels wrong - like there has to be a way to say:
the right one is always the same; you on the left - you get everything that's left
.ar-course-nav {
cursor: pointer;
padding: 8px 12px 8px 12px;
border-radius: 8px;
}
.ar-course-nav:hover {
background-color: rgba(0, 0, 0, 0.1);
}
<br/>
<br/>
<div class="ar-course-nav" style="display:flex; justify-content:space-between;">
<div style="width:96%;">
<div style="overflow:hidden; white-space:nowrap; text-overflow:ellipsis;">
<strong title="Course Name Which is Really Quite Long And Does Go On a Bit But Then When You Think it's Stopped it Keeps on Going for even longer!">
Course Name Which is Really Quite Long And Does Go On a Bit But Then When You Think it's Stopped it Keeps on Going for even longer!
</strong>
</div>
<div style="width:100%; display:flex; justify-content:space-between;">
<div style="color:#555555; margin-right:8px; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;" title="A really really really really really really really really really really really long department name">
A really really really really really really really really really really really long department name
</div>
<div style="color:#555555; text-align:right; white-space:nowrap;">
Created: 21 September 2016
</div>
</div>
</div>
<div style="margin-left:8px;">
<strong>></strong>
</div>
</div>
Use the flex-grow property to make a flex item consume free space on the main axis.
This property will expand the item as much as possible, adjusting the length to dynamic environments, such as screen re-sizing or the addition / removal of other items.
A common example is flex-grow: 1 or, using the shorthand property, flex: 1.
Hence, instead of width: 96% on your div, use flex: 1.
You wrote:
So at the moment, it's set to 96% which looks OK until you really squash the screen - then the right hand div gets a bit starved of the space it needs.
The squashing of the fixed-width div is related to another flex property: flex-shrink
By default, flex items are set to flex-shrink: 1 which enables them to shrink in order to prevent overflow of the container.
To disable this feature use flex-shrink: 0.
For more details see The flex-shrink factor section in the answer here:
What are the differences between flex-basis and width?
Learn more about flex alignment along the main axis here:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
Learn more about flex alignment along the cross axis here:
How does flex-wrap work with align-self, align-items and align-content?
Basically I was trying to get my code to have a middle section on a 'row' to auto-adjust to the content on both sides (in my case, a dotted line separator). Like #Michael_B suggested, the key is using display:flex on the row container and at least making sure your middle container on the row has a flex-grow value of at least 1 higher than the outer containers (if outer containers don't have any flex-grow properties applied, middle container only needs 1 for flex-grow).
Here's a pic of what I was trying to do and sample code for how I solved it.
.row {
background: lightgray;
height: 30px;
width: 100%;
display: flex;
align-items:flex-end;
margin-top:5px;
}
.left {
background:lightblue;
}
.separator{
flex-grow:1;
border-bottom:dotted 2px black;
}
.right {
background:coral;
}
<div class="row">
<div class="left">Left</div>
<div class="separator"></div>
<div class="right">Right With Text</div>
</div>
<div class="row">
<div class="left">Left With More Text</div>
<div class="separator"></div>
<div class="right">Right</div>
</div>
<div class="row">
<div class="left">Left With Text</div>
<div class="separator"></div>
<div class="right">Right With More Text</div>
</div>

Flex in IE11: width100% not working with nested flex and direction 'column'

I need an image in nested flex containers to have width 100%, but this doesn´t work in IE11 when the container has flex-direction: column. I tried:
img {
width: 100%;
max-width: calc( 100% - 0.1px );
}
but this also doesn't work. Any ideas?
section, .articles-wrapper, .article-wrapper {
display: flex;
}
.article-wrapper {
flex-direction: column;
}
img {
width: 100%;
}
html:
<section>
<div class="articles-wrapper">
<div class="article-wrapper">
<img src="http://via.placeholder.com/600x150">
</div>
</div>
</section>
Have you inspected the page to see how the elements are laid out?
The image actually is taking up 100% of it's parent's width, because by default flex-items are not allowed to grow to fill the flex container but expand only enough to display their content.
Both the .articles-wrapper and .article-wrapper elements need to be explicitly allowed to grow, either by specifying flex-grow: 1; or using the shorthand property flex with one of several values:
.articles-wrapper, .article-wrapper {
flex: auto; /* shorthand for flex: 1 1 auto; */
}
OR
.articles-wrapper, .article-wrapper {
flex: 1; /* shorthand for flex: 1 1 0%; */
}
As you get deeper into using flexbox, I recommend keeping Philip Walton's Flexbugs repo at hand which lists common bugs for all browsers as well as workarounds for each.
EDIT Michiel: flex: 1 works in IE11, except that the aspect ratio is not maintained when the window is scaled to a smaller size than the image size. This 'feature' is documented in Flexbugs #5, and can be solved by adding a non-flex wrapper:
<section>
<div class="articles-wrapper">
<div class="article-wrapper">
<div> <!-- ADDED NON-FLEX WRAPPER -->
<img src="http://via.placeholder.com/600x150">
</div>
</div>
</div>
</section>

Zurb Foundation 6 XY Grid using Grid Container within Flex-Container

I am using ZURB foundation 6 with XY grid and have run into a little problem and most likely something I'm doing wrong.
I want to center elements vertically so I use
<div class="flex-container">
<div class="grid-x grid-padding-x align-middle">
<div class="small-6 cell">Vertically Centered Left Column</div>
<div class="small-6 cell">Vertically Centered Left Column</div>
</div>
</div>
And using jQuery I set the height of flex-container by using windowHeight = $(window).innerHeight();
Voila the items are vertically aligned... However two issues arise from this:
small-6 cell has a width of 50% that is not being respected and shrinks down to the approx length of the text.
flex-container unlike grid-container does not have a width or padding.
To resolve the issue I added some CSS like so:
.flex-container .align-middle {
max-width: 62.5rem;
margin: 0 auto;
width: 100%;
}
So while I've patched the issue I can't help thinking that there must be an easier way, a proper way using just classes. It seems odd that grid-container is setup to do so but flex-container is not.
The main problem here is that with flex-container, the grid-x element will, along being a flex container of its own, also become a flex row item, having the default flex item value 0 1 auto.
This means the grid-x won't grow wider than its content, hence width: 50% won't work on its children (small-6), as their parent doesn't have a width set.
By adding e.g. flex-child-grow or cell to the grid-x element, it will fill its parent's width, and the inner flex items will start behave as expected.
Note 1: With grid-container this is not needed since it is not a flex container, where the grid-x is a normal div, displayed as flex, which, like a block element, by default take full width of its parent.
Note 2: Both flex-container and grid-container does have a default width of 100%, it is the grid-x, when being a flex item, that cause the issue not taking its parent's width by default.
Stack snippet
/* for demo purpose */
body { margin: 0; }
.flex-container { height: 100vh; }
.grid-x { border: 1px solid red; }
.small-6 { border: 1px solid blue; }
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.css" rel="stylesheet"/>
<div class="flex-container">
<div class="flex-child-grow grid-x grid-padding-x align-middle">
<div class="small-6 cell">Vertically Centered Left Column</div>
<div class="small-6 cell">Vertically Centered Left Column</div>
</div>
</div>

creating equal width flex items

I'm using flex for layout purposes, but the browser does not spread the width equally between items.
.parent {
display: flex;
width: 200px;
}
.btn1 {
flex: 1 1 auto;
}
<div class="parent">
<div class="btn1">
<button align="left" style="width:100%">Ok</button>
</div>
<button align="left" class="btn1">Cancel</button>
<div>
Now, I want the buttons to split the container length 50% / 50%.
But that's not what's happening. I tried using flex: 1 1 auto and flex: 1 1 0 but with no success.
I know that I can use the OK button directly and it will solve my problem, but in my particular scenario it's important to wrap it with a div.
Now, as I understand it, flex should be able to spread the width equally and that's my goal here.
One more thing though, I noticed that the button content seems to have an effect on the width and I want to ignore this effect somehow.
Thanks!
JSFiddle example:
https://jsfiddle.net/edismutko/cvytLkyp/3/
flex-basis: auto vs flex-basis: 0
You're sizing your flex items with flex: 1 1 auto.
However, if you want to distribute space evenly among items, you need to use flex: 1 1 0.
The difference is the flex-basis component.
With flex-basis: 0, every item is considered to have a zero width and flex-grow distributes container space equally among them. This results in all items having the same length.
With flex-basis: auto, the size of the item is factored into the flex-grow calculation and container space is distributed proportionally among items.
So when you want equal length items use flex: 1 1 0, which is the same as flex: 1.
Here's a more detailed explanation: Make flex-grow expand items based on their original size
Default rules on button elements
Browsers apply styles to elements by default. For instance, Chrome adds padding and border widths to button elements.
Reset those defaults.
Now you have two equal width flex items. (Additional styling is up to you.)
.parent {
display: flex;
width: 200px;
}
.btn1 {
flex: 1;
}
button {
padding: 1px 0;
border-left-width: 0;
border-right-width: 0;
}
<div class="parent">
<div class="btn1">
<button align="left" style="width:100%">Ok</button>
</div>
<button align="left" class="btn1">Cancel</button>
<div>
box-sizing: border-box
Something else to consider is including the padding and border lengths in the width / flex-basis calculation. Why are borders causing div to overflow container?