centered max-width doesn't fluid with display:flex - css

To center items with display: block people use margins: auto. If I set max-width to child that needs to be centered and there's enough space around it will fluid as much to max-width as it needs to (depending on its content). But if I change display property of parent element to flex it doesn't take all free space anymore. I really need to use max-width since I want element to shrink on small screens.
Here's the jsfiddle . Clicking on the button swaps display: flex to display: block on parent. I want the green space on flex to fluid as much as it's possible for max-width as it's done with display:block
EDIT:
I also would like to use flex-direction: column
$('input').click(function() {
var curDisplay = $('#parent').css('display');
if (curDisplay == 'block') {
$('#parent').css('display', 'flex');
$('input').val('flex');
} else {
$('#parent').css('display', 'block');
$('input').val('block');
}
})
#parent {
display: flex;
flex-direction: column;
width: 100%;
background-color: red;
height: 50px;
}
#child {
max-width: 300px;
background-color: green;
height: 50px;
margin: auto;
}
input {
width: 100%:
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
<div id="child">
<input type="button" value="Click Me!" />
</div>
</div>

I think you're looking for flex-basis. By using a % you can get very close. You can use px to set the initial width, it will still be "responsive" until you hit the minimum width if you have it set.
on the child element:
div {
flex-basis:40%;
}
Here is the W3

Why not just set the width of the child to 100%? If you need to center the button in the child you can simply add:
display: flex;
justify-content: center;
Also remove width: 100% from the input.

Related

CSS for having a scrollable div, take up 100% available height, but not add scroll bar to body

I'm trying to get a layout to work without any JS, just HTML and CSS.
top-div
left-div center-div right-div
The idea is to have vertical scroll bars on the center div, but nowhere else on the page, including the body.
It seemed like the best idea would be a vertical flexbox, to make the top row and bottom row, then a horizontal flexbox, to make left, center, and right.
How hard could that be?
Well, if you look at this fiddle, it's clearly too hard for me to make sense:
https://jsfiddle.net/gL4pwkxu/1/
The document always wants to stretch past the height of the window. Why?
Tricky to get working. From this SO post: Scrolling a flexbox with overflowing content, There's a need to add an element that creates its own height from the content. But I had to set the full-page height to 100vh (View Height units) AND set the height of content to anything and then it worked. See below...
CSS
html, body {
margin: 0px;
padding: 0px;
}
full-page {
display: flex;
flex-flow: column;
height: 100vh;
}
header {
background-color: green;
}
content {
flex: 1;
display: flex;
position: relative;
height: 1px; // hackery
}
nav {
background-color: red;
}
#right-column {
background-color: blue;
}
#main-column {
flex: 1;
overflow-y: auto; // used 'auto' so it only appears if you need it
}
#main-column > div {
min-height: min-content; // magic
}
HTML
<html>
<body>
<full-page>
<header>top</header>
<content>
<nav>left</nav>
<div id="main-column">
<div>
center<br>
b<br>
v<br>
d<br>
e<br>
e<br>
f<br>
f<br>
d<br>
e<br>
e<br>
f<br>
d<br>
e<br>
e<br>
f<br>
f<br>
f<br>
</div>
</div>
<div id="right-column">right</div>
</content>
</full-page>
</body>
</html>
I think the problem is that you are ignoring the height of the
<header>top</header> element
I also changed the height units to viewport height instead of %. Take a look: https://jsfiddle.net/zL6y7x2j/
hope it helps
To hide the window scroll add:
body {
overflow: hidden;
}
Then, to make the div scrollable:
#main-column {
overflow-y: scroll;
position: static;
}

How can I make this vertical list fill the vertical height of the container?

I am using flexbox to create my 2 column layout. Everything is working well, however I'd like to have my list items in my right column always take up the full height. Each <li> element contains an <img> element.
When I start to shrink the window width, as you can see, the <ul> element's height starts to scale up to keep it's aspect.
If I make the window really wide, the list element(s) will start to get clipped off.
I'd like to always be able to see all 4 list items. I'd be OK if I have to lock the width(s) or height(s) down. As you can see, I've set a min/max height but no luck. I am also OK with using the <li> elements as a container/viewable area for the images. Meaning, if the image inside the <li> gets clipped off overflow:hidden or something - that's fine. I am just trying to keep the two columns 50% each, and the right column always take the full height.
HTML
<div id="container">
<div id="foo">
...
</div>
<div id="bar">
<ul>
<li><img></li>
<li><img></li>
</ul>
</div>
</div>
CSS
#container {
display: flex;
flex-direction: row;
height: 600px;
min-height: 600px;
max-height: 600px;
}
#foo {
display: flex;
flex-direction: column;
order: 1;
width: 50%;
}
#bar {
display: flex;
flex-direction: column;
order: 2;
width: 50%;
}
Only give display: flex to the parent container. All children the inside parent container will be equal to the height of the child with the maximum height.
.container {
display: flex;
}
.foo {
width: 50%;
order: 1;
}
.bar {
width: 50%;
order: 2;
}

Flexbox: how to get divs to fill up 100% of the container width without wrapping?

I'm in the process of updating an old inline-block-based grid model I have to a newer Flexbox one I created. Everything has worked fine, apart from one little snag, which has become a bit of a dealbreaker:
I have a bunch of CSS-controlled sliders; so there's a containing wrapper with 100% width, and inside is another div: its width is also 100%, but its white-space is set to nowrap. Using inline-block, this meant that the internal divs (which were also set to 100% width) wouldn't be bound by their parents' constraints and wrap onto the next line - they'd just carry on flowing out of the box. This is exactly what I wanted. However, I cannot get this to work at all with flexbox. For reference, here's an image:
And for reference, here's a jsFiddle of the thing working with inline-block: http://jsfiddle.net/5zzvqx4b/
...and not working with Flexbox: http://jsfiddle.net/5zzvqx4b/1/
I've tried all kinds of variations with flex, flex-basis, flex-wrap, flex-grow, etc. but for the life of me I can't get this to work.
Note that I can force it to do what I want in a hacky, inflexible way by setting the .boxcontainer width to 200%. That works for this single example, but in some cases I won't know beforehand how many child boxes there will be, and I'd rather not resort to inline styling on each element if possible.
To prevent the flex items from shrinking, set the flex shrink factor to 0:
The flex shrink factor determines how much the flex item will
shrink relative to the rest of the flex items in the flex
container when negative free space is distributed. When omitted, it is
set to 1.
.boxcontainer .box {
flex-shrink: 0;
}
* {
box-sizing: border-box;
}
.wrapper {
width: 200px;
background-color: #EEEEEE;
border: 2px solid #DDDDDD;
padding: 1rem;
}
.boxcontainer {
position: relative;
left: 0;
border: 2px solid #BDC3C7;
transition: all 0.4s ease;
display: flex;
}
.boxcontainer .box {
width: 100%;
padding: 1rem;
flex-shrink: 0;
}
.boxcontainer .box:first-child {
background-color: #F47983;
}
.boxcontainer .box:nth-child(2) {
background-color: #FABCC1;
}
#slidetrigger:checked ~ .wrapper .boxcontainer {
left: -100%;
}
#overflowtrigger:checked ~ .wrapper {
overflow: hidden;
}
<input type="checkbox" id="overflowtrigger" />
<label for="overflowtrigger">Hide overflow</label><br />
<input type="checkbox" id="slidetrigger" />
<label for="slidetrigger">Slide!</label>
<div class="wrapper">
<div class="boxcontainer">
<div class="box">
First bunch of content.
</div>
<div class="box">
Second load of content.
</div>
</div>
</div>
You can use the shorthand flex property and set it to
flex: 0 0 100%;
That's flex-grow, flex-shrink, and flex-basis in one line. Flex shrink was described above, flex grow is the opposite, and flex basis is the size of the container.
In my case, just using flex-shrink: 0 didn't work. But adding flex-grow: 1 to it worked.
.item {
flex-shrink: 0;
flex-grow: 1;
}
Set the flex-direction: column
You're trying to stack the items in a column rather than a row.
{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}

flex-basis not working as expected

As i understand flex-basis is responsible for deciding the size of an element.
In the example below, I am trying to size all boxes equally to 100px.
Just using flex-basis is not achieving the effect.
.each_box {
-webkit-flex-grow: 0;
-webkit-flex-shrink: 0;
-webkit-flex-basis: 100px;
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100px;
background-color: yellow;
height: 50px;
border: 1px solid black;
}
Plnkr here: http://plnkr.co/edit/LvrrzHWIw1tPGwK05bCU
I found I had to use min-width as well as flex-basis in Chrome. I'm not sure if I had another problem that caused this.
.flex-container {
display: flex;
width: 100%;
}
.flex-child {
flex-basis: 50%;
min-width: 50%;
}
Be sure to also add: flex-wrap: wrap; because the default value nowrap in order to fit everything in one line can affect the size of the elements (eg: width, flex-basis, etc..).
The flex-grow, flex-shrink, flex-basis properties only have an effect on elements in a flex container -- i.e. elements whose parent has display:flex.
You need to put your each_box divs directly inside of a display:flex element for them to honor their flex-related properties.
Specifically, your markup looks like this (from right clicking one of the yellow divs + hitting "inspect" in Firefox):
<div class="container">
<!-- ngRepeat: stock in stockList -->
<div class="ng-scope" ng-repeat="stock in stockList">
<div class="each_box ng-binding">
0-FB/100
You've got container styled as display:flex, but that does no good for your each_box elements, because they're grandchildren, separated from the flex container by the display:block ng-scope.
So you either need to get rid of the ng-scope wrapper, or make it also have display:flex.
Add a width: width:100px;
flex-basis gives a default proportion, which will then grow or shrink.
All works for me:
.flex-child { width:0; }
AND
.flex-child { min-width:0; }
AND
.flex-child { flex-shrink:0; } /* no scrollbars inside */

Two divs with fixed widths need equidistant spacing in a parent div

I have two divs (which have a fixed width of 150px) within another parent div, which has a changing width, depending on the browser width.
I would like to position the two child divs within the parent, so the margin between the two divs would be equal to the margins between the edges of the parent div and child divs.
Example with red arrows always having equal lenghts:
edit: you could do what I first suggested, but now add
#leftwrapper, #rightwrapper { text-align: center; }
#childdiv1, #childdiv2 { display: inline-block; }
inline-block, instead of block, and you don't need the margins then for child div...
if that don't work, which probably won't, it might be VERY hard to get what you want to happen without using a table
you would have to create two new div wrappers
so you have
#parentdiv { display: block; width: 100%; }
#leftwrapper { display: inline-block; width: 50%; }
#rightwrapper { display: inline-block; width: 50%; }
#childdiv1 { display: block; margin: 0 auto; }
#childdiv2 { display: block; margin: 0 auto; }
html would be like
<div id="parentdiv">
<div id="leftwrapper">
<div id="childdiv1">your stuff</div>
</div>
<div id="rightwrapper">
<div id="childdiv2">your stuff</div>
</div>
</div>

Resources