CSS outline around a flex element not including child element margin? - html

I am using an outline and a margin in an attempt to avoid a double border around some flex-elements.
If I apply a margin to the flex element itself it works as expected. However, if I apply the margin to a child element the double border shows up again.
Why does the outline correctly render only when the margin is applied to the parent flex element? Is this a bug?
.comment {
padding:20px;
}
#flex-container {
display: flex;
}
.flex-element {
flex-grow: 1;
}
.flex-content {
width: 100%;
height: 100%;
margin-left: 5px;
outline: 5px solid #ccc;
}
.flex-element-working {
flex-grow: 1;
margin-left: 5px;
}
.flex-content-working {
width: 100%;
height: 100%;
outline: 5px solid #ccc;
}
<div class='comment'>
Why doesn't this work?:
</div>
<div id='flex-container'>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
</div>
<div class='comment'>
Working Example:
</div>
<div id='flex-container'>
<div class='flex-element-working'>
<div class='flex-content-working'>
<div class='comment'> Flex Content</div>
</div>
</div>
<div class='flex-element-working'>
<div class='flex-content-working'>
<div class='comment'> Flex Content</div>
</div>
</div>
</div>

The point is in the top flex container (bad working) in double outline the left on is for the right div and the right one is for left div! Please add this style to your code:
.flex-content{background-color:red;}
You will see the out line is how you want.
.flex-content divs have width 303px But .flex-content-working divs have width 298px so in second one we have not such problem.
To see the width of your elements use developer tools of your browser and layout or box menu.

A bit another approach using padding and box-shadow:
#flex-container {
box-shadow: inset 0 0 0 2px red;
display: flex;
padding: 2px;
}
.flex-element {
flex-grow: 1;
box-shadow: inherit;
}
.comment {
padding: 20px;
}
<div id='flex-container'>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
<div class='flex-element'>
<div class='flex-content'>
<div class='comment'> Flex Content</div>
</div>
</div>
</div>

Related

Can I make a scrollbar start after the container's padding?

I have a horizontal scroll container like in the image below. It has some horizontal padding which causes the scrollbar to start too far on the left. It needs the padding so that the shadows below the cards don't get cut off by the container.
I'd like to keep the padding and make the scrollbar start where the first card starts like this:
Here's the code for the general layouts (also in Codepen):
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
p {
text-align: center;
margin: 20px 0 10px;
}
.container {
border: 1px solid;
width: 500px;
margin: 0 auto;
display: flex;
gap: 10px;
overflow: auto;
padding: 10px 0;
}
.horizontal-padding {
padding-left: 30px;
padding-right: 30px;
}
.content {
box-shadow: 0 0 5px 0;
flex: 0 0 100px;
}
<p>Current layout with padding where scrollbar starts too far on the left:</p>
<div class="container horizontal-padding">
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
</div>
<p>Layout without padding where scrollbar starts nicely with the content but shadows are cut off:</p>
<div class="container">
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
<div class="content">Sample Content</div>
</div>
One of the posibilities is adding padding on the containers and see how much would you want to put in
or another option is to make a box or container new that you adapt it with your preferences
Also another option is using the border property of the same color that the backgounrd

Flex child of child does not expand to 100%

In CSS, if a child of a child is set to width: 100% and the wrapping div has display: flex set, the content does not expand to 100% it only uses the space of the content.
How would one make it expand to the size the grandchild sets itself but still use flex?
flex-grow is probably not the answer since this will always expand to take up the full space and not respect the size the grandchild sets itself.
See following example:
.wrapperFlex, .wrapperBlock{
border: 1px solid silver;
}
.wrapperFlex {
display: flex;
}
.levelOne {
}
.levelOneGrow {
flex-grow: 1;
}
.levelTwo, .levelTwoFullWidth {
color: white;
background-color: blue;
}
.levelTwoFullWidth {
width: 100%;
}
.levelOnePassthrough{
display: contents;
}
<!-- Premise -->
<div class="wrapperFlex">
<div>PRE</div>
<div class="levelOne">
<div class="levelTwoFullWidth">
WRAPPER FLEX
</div>
</div>
<div>AFTER</div>
</div>
<br/>
<!-- Not what is wanted, the grandchild here does not actually expand to 100%
it should be only as wide as the content here -->
<div class="wrapperFlex">
<div>PRE</div>
<div class="levelOneGrow">
<div class="levelTwo">
WRAPPER FLEX GROW
</div>
</div>
<div>AFTER</div>
</div>
<br/>
<!-- What is wanted but not possible, display: contents is not commonly available -->
<div class="wrapperFlex">
<div>PRE</div>
<div class="levelOnePassthrough">
<div class="levelTwoFullWidth ">
WRAPPER FLEX PASSTHROUGH
</div>
</div>
<div>AFTER</div>
</div>
Can you set flex-basis to the child?
.wrapperFlex, .wrapperBlock{
border: 1px solid silver;
}
.wrapperFlex {
display: flex;
}
.wrapperBlock {
display: block;
}
.levelOne {
flex-basis: 100%; /* Set flex-basis to 100% */
}
.levelTwo {
color: white;
width: 100%;
background-color: blue;
}
<div class="wrapperFlex">
<div class="levelOne">
<div class="levelTwo">
WRAPPER FLEX
</div>
</div>
</div>
<br/>
<div class="wrapperBlock">
<div class="levelOne">
<div class="levelTwo">
WRAPPER BLOCK
</div>
</div>
</div>
set .levelOne {width:100%} ,if im not misunderstanding you.
You need to add the flex property as one to the child i.e levelOne like this flex:1;.
It will work properly as you check here.
.wrapperFlex, .wrapperBlock{
border: 1px solid silver;
}
.wrapperFlex {
display: flex;
}
.wrapperBlock {
display: block;
}
.levelOne {
flex:1;
}
.levelTwo {
color: white;
width: 100%;
background-color: blue;
}
<div class="wrapperFlex">
<div class="levelOne">
<div class="levelTwo">
WRAPPER FLEX
</div>
</div>
</div>
<br/>
<div class="wrapperBlock">
<div class="levelOne">
<div class="levelTwo">
WRAPPER BLOCK
</div>
</div>
</div>

Control width of flex items arranged vertically in a flex container

I'm trying to achieve the effect where the boxes labeled "HALF", take up only 50% of the width (aka they share the first row evenly).
The base requirement is that they remain in a single container. Is this possible to achieve using flexbox?
I've tried playing around with flex-grow, flex-shrink, and flex-basis but I'm afraid I'm not understanding how to make it work, or if it's even possible, given the single container requirement.
Consider this fiddle: http://jsfiddle.net/GyXxT/270/
div {
border: 1px solid;
}
.container {
width: 400px;
display: flex;
flex-direction: column;
}
.child {
height: 200px;
}
.child.half {
flex: 1 1 10em;
color: green;
}
.child:not(.half) {
flex-shrink: 2;
flex-basis: 50%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
Instead of flex-direction: column, you can try a wrapping flexbox using flex-wrap: wrap; and you can set:
flex-basis: 50% for the half width divs
flex-basis: 100% for the full width divs
See that I have thrown in box-sizing: border-box to adjust for the widths when using flex-basis.
See demo below:
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
display: flex;
flex-wrap: wrap;
}
.child {
height: 200px;
}
.child.half {
flex-basis: 50%;
color: green;
}
.child:not(.half) {
flex-basis: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
The flex sizing properties -- flex-grow, flex-shrink, flex-basis and flex -- work only along the main axis of the flex container.
Since your container is flex-direction: column, the main axis is vertical, and these properties are controlling height, not width.
For sizing flex items horizontally in a column-direction container you'll need the width property.
(Here's a more detailed explanation: What are the differences between flex-basis and width?)
To achieve your layout with a single container, see another answer to this question.
If you want to stay in column-direction, you'll need to wrap the .half elements in their own container.
.container {
display: flex;
flex-direction: column;
width: 400px;
}
.container > div:first-child {
display: flex;
}
.child.half {
flex: 1 1 10em;
color: green;
width: 50%;
}
.child {
height: 200px;
width: 100%;
border: 1px solid;
}
* {
box-sizing: border-box;
}
<div class="container">
<div><!-- nested flex container for half elements -->
<div class="child half">HALF</div>
<div class="child half">HALF</div>
</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
</div>
The base requirement is that they remain in a single container.
That can also be done without flexbox, by simply float the 2 half elements
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
}
.child {
height: 200px;
}
.child.half {
float: left;
width: 50%;
color: green;
}
.child:not(.half) {
width: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
If the purpose is to hardcode the size in CSS units, or in percentages (which was mentioned the question), #kukkuz's solution is good as it is.
If you want to size element widths according to their own individual contents, then align-tems: flex-start or similar could do the job. It's possible to deal with the dimension perpendicular to that of the flex layout itself. See a tester on the bottom of the doc page
(Old question, but previous answers were incomplete, some are misleading)

Equal height flex items when inner content has different height

I need columns that will have the same height, so I used flex (I use bootstrap framework).
I know that flex work can be seen in the attached picture, but the height of the boxes is not the same, by the fact that one is less text than the other.
I want class inner-div to match to the height of col-md-4.
Can someone help me adjust the height so that it is always the same?
.col-md-4 {
border: 1px solid black;
}
.row-eq-height {
display: flex;
}
.inner-div {
border: 1px solid red;
}
<div class="container">
<div class="row row-eq-height">
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>
<div class="inner-div">
adsadadadada
</div>
</div>
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<div class="inner-div">
asdadadaada
</div>
</div>
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>
<div class="inner-div">
asdadaadas
</div>
</div>
</div>
</div>
The problem is that .inner-div is not a flex item, so it doesn't accept flex properties.
Flex layout works only within a parent-child relationship. .row-eq-height is a flex container because you've given it display: flex. This means that .col-md-4 is a flex item, because it's the child of .row-eq-height.
Looking at your images (the highlighted section), you'll see that flex equal height columns are actually working. Each .col-md-4 container is the same height.
However, the children of .col-md-4 are not flex items. They are normal elements in a block, not flex, formatting context.
The solution is to make .col-md-4 a flex container so flex properties can be applied to .inner-div.
.row-eq-height {
display: flex;
}
.col-md-4 {
display: flex;
flex-direction: column;
border: 1px solid black;
}
.inner-div {
flex: 1;
border: 1px solid red;
}
<div class="row row-eq-height">
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>
<div class="inner-div">
adsadadadada
</div>
</div>
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<div class="inner-div">
asdadadaada
</div>
</div>
<div class="col-md-4">
ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>ddddddsadddddddsadddddddsadddddddsa
<br>
<div class="inner-div">
asdadaadas
</div>
</div>
</div>
It's simple.
When you want to set the inner-div's height to it's parent's height, set the inner-div to display:flex and flex-grow:1. It will take up the height of the parent.
Additionally you can set align-items: stretch to the parent div. This makes all the inner divs to stretch out to what the parent has.
Hope it works for you.
I think you are looking for a solution like this: https://jsfiddle.net/Lddyn573/4/
I set the height of the box-header to calc(100% -24px), 24px is the height of the bottom div.
/* CSS used here will be applied after bootstrap.css */
.col-md-4 {
border: 1px solid black;
padding: 10px;
}
.row-eq-height {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.box-header{
height: calc(100% - 24px);
border: 1px solid green;
}
.box-content {
border: 1px solid red;
}

Flexbox many nested children

I've read many posts on flexbox but still have an issue that bugs me.
I want to have a sticky footer using flexbox as per this guide.
But then, inside my page content I would like to have as many nested divs I like and have them taking the same height of the parent.
The problem is, setting height: 100% on each child (as I would do in a non-flexbox scenario) works differently when flexbox is enabled. This results in the children getting more height (overflow the parent).
To make this more clear here's a codepen without flexbox
and a codepen with flexbox
You can see in the flexbox scenario the footer gets the green bakground even if I don't want that.
HTML:
<div class="sticky-footer-container">
<div class="sticky-footer-content">
<div class="page-container">
<div class="main-menu">
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sticky-footer">
Some footer content
</div>
</div>
SCSS:
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
background: silver;
padding: 0;
margin: 0;
}
.sticky-footer-container {
height: 100%;
display: flex;
flex-direction: column;
.sticky-footer-content {
height: 100%;
background: blue;
flex: 1;
div {
height: 100%;
}
.main-menu-selection {
height: 50%;
}
}
}
.some-other-class {
background: green;
}
In order to solve this, ANY nested div has to become a flex-container ?
In other words, is there any way to "stop the flex propagation" at some point of the tree, so all the divs gets the parent height without overflow?
display:flexbox is not really a valid value :)
you need to set height as well and eventually inherit it from html :
.sticky-footer-container {
display: flex;
flex-direction: column;
}
.sticky-footer-content {
flex: 1;
}
/* let's inherit some height to pull the footer down */
html,
body,
.sticky-footer-container {
height: 100%;
margin: 0;
}
.sticky-footer {
display: flex;/* flex item can be flexboxes as well */
background: turquoise;
align-items: center;
justify-content: center;
min-height: 3em;
}
<div class="sticky-footer-container">
<div class="sticky-footer-content">
<div class="page-container">
<div class="main-menu">
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
<div class="main-menu-selection">
<div class="main-menu-selection-text">
<div class="some-other-class">
Some text
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sticky-footer">
Here my footer
</div>
</div>