Why does display: flex push the following element onto a new line? - html

In my code, the first example works fine. The second one pushes the second element to a new line.
Why? and how to avoid it?
see this codepen
.one {
background-color: cornflowerblue;
width: 50%;
}
.one,
.two {
height: 100%;
font-size: 30px;
}
.two {
width: 50%;
background-color: salmon;
}
.ib {
display: inline-block;
}
.container {
font-size: 0;
height: 200px;
}
.fb {
display: flex;
}
<div class="container">
<div class="one ib">one</div>
<div class="two ib">two</div>
</div>
<div class="container">
<div class="one fb">one</div>
<div class="two ib">two</div>
</div>

You have three divs that have their display value set to inline-block. Each of these divs has a class ib.
You have one div with display: flex. This div has a class fb.
When you apply display: flex to an element it becomes a block-level container. As a block-level element, it takes up all available space in the line, pushing any subsequent elements to the next line.
The way to solve this problem is to use display: inline-flex instead of display: flex.
Revised Codepen
From the spec:
3. Flex Containers: the flex and inline-flex display
values
flex
This value causes an element to generate a block-level flex container
box.
inline-flex
This value causes an element to generate an inline-level flex
container box.

.fb{
display: inline-flex;
}
If you use the above code you could see the difference easily.
An inline element does not start on a new line and only takes up as much width as necessary.
But flex will start on a new line .

flex is actually the property you apply and enable at a container/parent level. It's not clear from your example what exactly you expect the your child divs (one and two) to do?
See this updated pen where I've removed the ib and fb classes from the children and applied fb to the second container parent: http://codepen.io/angeliquejw/pen/qZRoLz?editors=1100
Also, CSS-Tricks has a fab breakdown that helps understand the basics of flexbox: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Updated to reflect response below: flex, which you used initially,behaves more like block (see docs: https://developer.mozilla.org/en-US/docs/Web/CSS/display). You want to use display:inline-flex : http://codepen.io/angeliquejw/pen/jqyxNz?editors=1100

Related

How to make 2 divs the same height

I am trying to get 2 divs that do not have a common parent div to be the height of the larger div. (using display: flex).
As shown in the above code, I would like <child-div1> and <child-div2> to have the same height. Currently, I have display: flex on the <parent-div> which successfully makes <middle-div1> and <middle-div2> to have the same height. However, I can't seem to figure out how to ensure that <child-div1> and <child-div2> have the same height.
<parent-div style="display: flex">
<middle-div1>
<child-div1></child-div1>
</middle-div1>
<middle-div2>
<child-div2></child-div2>
</middle-div2>
</parent-div>
In order to figure it out you could right click in the page, then select inspect element, and you going to see a window like this:
by clicking the most left icon and hovering over the two divs, you are going to see the exact width x height
Add display: flex to the <middle-div> flex items.
This will automatically apply align-items: stretch to the <child-div> children. (Just note that a height rule will override align-items: stretch.)
With that layout, you can set both children to have height: inherit; it's inheriting the height from the tallest part of the container. So for example, if you have an image on one side that is 400 px tall, that stretches the container, therefore, allowing the other child to grow in height also.
.container {
display: flex;
}
.one, .two {
height: inherit;
width: 50%;
}
.one {
background-color: lightblue;
}
.two {
background-color: darkgreen;
color: white;
}
<div class="container">
<div class="one">1<br><img src="https://dummyimage.com/400x400/000/fff&text=test"></div>
<div class="two">2</div>
</div>
One solution is to add height:100%; to child-div1 and child-div2
<parent-div style = "display: flex">
<middle-div1>
<child-div1 style="height: 100%;"></child-div1>
</middle-div1>
<middle-div2>
<child-div2 style="height: 100%;"></child-div2>
</middle-div2>
</parent-div>

Sidebar getting pushed down

My sidebar is getting pushed down instead of staying inline with my main class, you can view the issue more in my fiddle. (This is one of the first times I've not used bootstrap for a project in a very long time).
view my fiddle.
Instead of float, using flex is a better approach for responsive design.
Try putting your sidebar and main inside a div with display as flex and flex-wrap as wrap.
Here's an example-
.flexbox {
display: flex;
flex-wrap: wrap;
}
.latest-single {
width: 70%;
background-color: blue;
}
.sidebar {
width: 30%;
background-color: green;
}
<div class="flexbox">
<div class="latest-single">
This is our primary content
</div>
<div class="sidebar">
This is our sidebar content
</div>
</div>
You have to choose a way of how to display them. (block,flex,table)
i made it working by adding the display:flex on .container class.
jsfiddle https://jsfiddle.net/31rjm8qb/7/
You have a couple of problems here.
.main has width 100% so .sidebar can not fit
.sidebar is floated while .main is not, so they will not line up
I think it would be a good idea to try out display: flexbox and remove floats altogether.
Check out the following article: https://css-tricks.com/snippets/css/a-guide-to-flexbox/

How to vertically center div relative to flexbox grandparent?

Given a div with display flexbox .wrapper (run and see snippet below) and a deeply nested div .text-container, how can I center the deeply nested div relative to the .wrapper and not relative to its parent .variable-height?
In the snippet below there are two columns with equal height and I want the text, which is placed in a variable height div inside each column, to be at the same level. I have set the display of the variable height div also to flexbox, so logically the text is centered, relative to it and not to the grandparent .wrapper, which is not what I want.
The only solution I came up with is to set position: relative; on .wrapper and on .text-container:
position: absolute;
top: 50%;
transform: translateY(-50%);
However, I am not sure, if it's a good idea to mix flexbox and absolute/relative positioning.
.wrapper {
background-color: white;
min-height: 200px;
width: 200px;
float: left;
margin-left: 50px;
display: flex;
flex-direction: column;
}
.wrapper .fixed-height {
background-color: orange;
min-height: 30px;
}
.wrapper .second {
background-color: yellow;
min-height: 30px;
}
.wrapper .variable-height {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.wrapper .variable-height .text-container {
width: 100%;
text-align: center;
}
<div class="wrapper">
<div class="fixed-height"></div>
<div class="fixed-height second"></div>
<div class="variable-height">
<div class="text-container">
<div class="title">Title</div>
<div class="subtitle">Subtitle</div>
</div>
</div>
<div class="fixed-height"></div>
</div>
<div class="wrapper">
<div class="fixed-height"></div>
<div class="variable-height">
<div class="text-container">
<div class="title">Title</div>
<div class="subtitle">Subtitle</div>
</div>
</div>
<div class="fixed-height"></div>
</div>
However, I am not sure, if it's a good idea to mix flexbox and absolute/relative positioning.
Well, it depends on what sort of behavior is acceptable to you.
When you absolutely position an element, you remove it from the document flow.
So, in this case, .wrapper and its flex items don't know that .text-container exists. If there's any flexibility to the container or items, they will overlap with .text-container. See this illustration:
Centering: Absolute Positioning vs Flexbox (re-size the window to see the difference)
Again, if the overlapping is acceptable to you, then absolute positioning is fine.
In terms of the flexbox specification, there's nothing wrong with mixing absolute / relative positioning with flex properties. The spec has a section on this subject:
4.1. Absolutely-Positioned Flex Children
An absolutely-positioned child of a flex container does not participate in flex layout. However, it does participate in the reordering step (see order), which has an effect in their painting order.
The static position of an absolutely-positioned child of a flex container is determined such that the child is positioned as if it were the sole flex item in the flex container, assuming both the child and the flex container were fixed-size boxes of their used size.
The effect of this is that if you set, for example, align-content: center; on an absolutely-positioned child of a flex container, the child’s static position will center it in the flex container’s cross axis.
Two things to note from the spec:
Although an absolutely positioned flex item is removed from the document flow (as expected), it still recognizes the order property.
You can still use flex properties to center an absolutely positioned flex item, but only under certain circumstances and only within the parent container, not the grandparent.

How can I easily align an element with "display: inline-block" and "overflow: hidden"?

inline-block elements using overflow: hidden position themselves so their bottom margin is the baseline. From http://www.w3.org/TR/CSS2/visudet.html#leading:
The baseline of an 'inline-block' is the baseline of its
last line box in the normal flow, unless it has either no
in-flow line boxes or if its 'overflow' property has a
computed value other than 'visible', in which case the
baseline is the bottom margin edge.
In practice this means these elements are shifted up unexpectedly; e.g., inside a <td> the element will not be vertically centered. A simpler example:
div {
border: 1px solid red;
text-decoration: underline;
}
.ib {
display: inline-block;
}
.h {
overflow: hidden;
}
<div>
<div class="ib">Visible</div>ABgjh</div><br>
<div>
<div class="ib h">Hidden</div>ABgjh</div>
the div with overflow: hidden doesn't share the same baseline as its surrounding line.
I'm looking for a simple way to make that div align itself as if it was following the normal rules for inline-block elements. Basically I want to write a custom element that "just works" whether its consumer applies a vertical-align style, or places it inside a <td>, etc.
This table has an example where I want the element to vertically center itself but instead it pushes itself up (and the rest of the line down).
This fiddle has more examples showing how different pairings of vertical-align behave unexpectedly when one element is display: inline-block; overflow: hidden.
To be clear, this question is asking whether a <div style="overflow: hidden"> can be wrapped in such a way that it can be treated as a regular inline-block element, positioning itself intelligently, without JS or font-based pixel adjustments. I'd want to be able to apply styling to the final component in order to position or align it as I please, as if it were a regular inline-block element.
I am not sure what browsers you are looking to support but if you wrap your DIV with display: flex; you wont get that vertical offset. You can see it here:
div {
border: 1px solid red;
text-decoration: underline;
}
.ib {
display: inline-block;
}
.h {
overflow: hidden;
}
.flex {
display: flex;
}
<div>
<div class="ib">Visible</div>
ABgjh
</div>
<div class="flex">
<div class="ib h">Hidden</div>
ABgjh
</div>
I normally don't use flexbox because of the lack of browser support but perhaps this is the simple solution you're looking for. Hope that helps.

How can I expand floated child div's height to parent's height?

I have the page structure as:
<div class="parent">
<div class="child-left floatLeft">
</div>
<div class="child-right floatLeft">
</div>
</div>
Now, the child-left DIV will have more content, so the parent DIV's height increases as per the child DIV.
But the problem is child-right height is not increasing. How can I make its height as equal to it's parent?
For the parent element, add the following properties:
.parent {
overflow: hidden;
position: relative;
width: 100%;
}
then for .child-right these:
.child-right {
background:green;
height: 100%;
width: 50%;
position: absolute;
right: 0;
top: 0;
}
Find more detailed results with CSS examples here and more information about equal height columns here.
A common solution to this problem uses absolute positioning or cropped floats, but these are tricky in that they require extensive tuning if your columns change in number+size, and that you need to make sure your "main" column is always the longest. Instead, I'd suggest you use one of three more robust solutions:
display: flex: by far the simplest & best solution and very flexible - but unsupported by IE9 and older.
table or display: table: very simple, very compatible (pretty much every browser ever), quite flexible.
display: inline-block; width:50% with a negative margin hack: quite simple, but column-bottom borders are a little tricky.
1. display:flex
This is really simple, and it's easy to adapt to more complex or more detailed layouts - but flexbox is only supported by IE10 or later (in addition to other modern browsers).
Example: http://output.jsbin.com/hetunujuma/1
Relevant html:
<div class="parent"><div>column 1</div><div>column 2</div></div>
Relevant css:
.parent { display: -ms-flex; display: -webkit-flex; display: flex; }
.parent>div { flex:1; }
Flexbox has support for a lot more options, but to simply have any number of columns the above suffices!
2.<table> or display: table
A simple & extremely compatible way to do this is to use a table - I'd recommend you try that first if you need old-IE support. You're dealing with columns; divs + floats simply aren't the best way to do that (not to mention the fact that multiple levels of nested divs just to hack around css limitations is hardly more "semantic" than just using a simple table). If you do not wish to use the table element, consider css display: table (unsupported by IE7 and older).
Example: http://jsfiddle.net/emn13/7FFp3/
Relevant html: (but consider using a plain <table> instead)
<div class="parent"><div>column 1</div><div>column 2</div></div>
Relevant css:
.parent { display: table; }
.parent > div {display: table-cell; width:50%; }
/*omit width:50% for auto-scaled column widths*/
This approach is far more robust than using overflow:hidden with floats. You can add pretty much any number of columns; you can have them auto-scale if you want; and you retain compatibility with ancient browsers. Unlike the float solution requires, you also don't need to know beforehand which column is longest; the height scales just fine.
KISS: don't use float hacks unless you specifically need to. If IE7 is an issue, I'd still pick a plain table with semantic columns over a hard-to-maintain, less flexible trick-CSS solution any day.
By the way, if you need your layout to be responsive (e.g. no columns on small mobile phones) you can use a #media query to fall back to plain block layout for small screen widths - this works whether you use <table> or any other display: table element.
3. display:inline block with a negative margin hack.
Another alternative is to use display:inline block.
Example: http://jsbin.com/ovuqes/2/edit
Relevant html: (the absence of spaces between the div tags is significant!)
<div class="parent"><div><div>column 1</div></div><div><div>column 2</div></div></div>
Relevant css:
.parent {
position: relative; width: 100%; white-space: nowrap; overflow: hidden;
}
.parent>div {
display:inline-block; width:50%; white-space:normal; vertical-align:top;
}
.parent>div>div {
padding-bottom: 32768px; margin-bottom: -32768px;
}
This is slightly tricky, and the negative margin means that the "true" bottom of the columns is obscured. This in turn means you can't position anything relative to the bottom of those columns because that's cut off by overflow: hidden. Note that in addition to inline-blocks, you can achieve a similar effect with floats.
TL;DR: use flexbox if you can ignore IE9 and older; otherwise try a (css) table. If neither of those options work for you, there are negative margin hacks, but these can cause weird display issues that are easy to miss during development, and there are layout limitations you need to be aware of.
For the parent:
display: flex;
For children:
align-items: stretch;
You should add some prefixes, check caniuse.
I found a lot of answers, but probably the best solution for me is
.parent {
overflow: hidden;
}
.parent .floatLeft {
# your other styles
float: left;
margin-bottom: -99999px;
padding-bottom: 99999px;
}
You can check other solutions here http://css-tricks.com/fluid-width-equal-height-columns/
Please set parent div to overflow: hidden
then in child divs you can set a large amount for padding-bottom. for example
padding-bottom: 5000px
then margin-bottom: -5000px
and then all child divs will be the height of the parent.
Of course this wont work if you are trying to put content in the parent div (outside of other divs that is)
.parent{
border: 1px solid black;
overflow: hidden;
height: auto;
}
.child{
float: left;
padding-bottom: 1500px;
margin-bottom: -1500px;
}
.child1{
background: red;
padding-right: 10px;
}
.child2{
background: green;
padding-left: 10px;
}
<div class="parent">
<div class="child1 child">
One line text in child1
</div>
<div class="child2 child">
Three line text in child2<br />
Three line text in child2<br />
Three line text in child2
</div>
</div>
Example: http://jsfiddle.net/Tareqdhk/DAFEC/
Does the parent have a height? If you set the parents height like so.
div.parent { height: 300px };
Then you can make the child stretch to the full height like this.
div.child-right { height: 100% };
EDIT
Here is how you would do it using JavaScript.
CSS table display is ideal for this:
.parent {
display: table;
width: 100%;
}
.parent > div {
display: table-cell;
}
.child-left {
background: powderblue;
}
.child-right {
background: papayawhip;
}
<div class="parent">
<div class="child-left">Short</div>
<div class="child-right">Tall<br>Tall</div>
</div>
Original answer (assumed any column could be taller):
You're trying to make the parent's height dependent on the children's height and children's height dependent on parent's height. Won't compute. CSS Faux columns is the best solution. There's more than one way of doing that. I'd rather not use JavaScript.
I used this for a comment section:
.parent {
display: flex;
float: left;
border-top:2px solid black;
width:635px;
margin:10px 0px 0px 0px;
padding:0px 20px 0px 20px;
background-color: rgba(255,255,255,0.5);
}
.child-left {
align-items: stretch;
float: left;
width:135px;
padding:10px 10px 10px 0px;
height:inherit;
border-right:2px solid black;
}
.child-right {
align-items: stretch;
float: left;
width:468px;
padding:10px;
}
<div class="parent">
<div class="child-left">Short</div>
<div class="child-right">Tall<br>Tall</div>
</div>
You could float the child-right to the right, but in this case I've calculated the widths of each div precisely.
I have recently done this on my website using jQuery. The code calculates the height of the tallest div and sets the other divs to the same height. Here's the technique:
http://www.broken-links.com/2009/01/20/very-quick-equal-height-columns-in-jquery/
I don't believe height:100% will work, so if you don't explicitly know the div heights I don't think there is a pure CSS solution.
If you are aware of bootstrap you can do it easily by using 'flex' property.All you need to do is pass below css properties to parent div
.homepageSection {
overflow: hidden;
height: auto;
display: flex;
flex-flow: row;
}
where .homepageSection is my parent div.
Now add child div in your html as
<div class="abc col-md-6">
<div class="abc col-md-6">
where abc is my child div.You can check equality of height in both child div irrespective of border just by giving border to child div
<div class="parent" style="height:500px;">
<div class="child-left floatLeft" style="height:100%">
</div>
<div class="child-right floatLeft" style="height:100%">
</div>
</div>
I used inline style just to give idea.
I can see that the accepted answer uses position: absolute; instead of float: left. In case you want to use float: left with the following structure,
<div class="parent">
<div class="child-left floatLeft"></div>
<div class="child-right floatLeft"></div>
</div>
Give position: auto; to the parent so that it will contain its children height.
.parent {
position: auto;
}
.floatLeft {
float: left
}
I learned of this neat trick in an internship interview. The original question is how do you ensure the height of each top component in three columns have the same height that shows all the content available. Basically create a child component that is invisible that renders the maximum possible height.
<div class="parent">
<div class="assert-height invisible">
<!-- content -->
</div>
<div class="shown">
<!-- content -->
</div>
</div>