CSS flexbox giving unexpected output - html

I have below markup for testing flexbox:
<html>
<head>
<style>
.parent{
display: flex;
flex-direction: column;
}
.parent>div>button{
display: flex;
}
.parent>div:nth-child(2){
display: flex;
}
</style>
</head>
<body>
<div class="parent">
<div class="div1"><button>butt1</button><button>butt7</button></div>
<div class="div2"><button>butt2</button><button>butt3</button><button>butt4</button>
<button>butt5</button><button>butt6</button></div>
</div>
</body>
</html>
Its output is given below:
What I don't understand is that even if we haven't given any flex-direction: column to the div1 i.e., we haven't written:
.parent>div>button{
display: flex;
flex-direction: column;
}
even then butt1 and butt7 are aligned in column. Why they are not aligned in row?? Is it the case that child div inherits the value of flex-direction of parent? I have read that default value of flex-direction is row. So, with that logic as well, they should have been aligned row-wise, not column-wise.
Please help me to find the reason of above behaviour.
Thank You.

The problem is in this:
.parent>div>button{
display: flex;
}
You overwritten default style of button, which is display: inline-block. display: flex works for children not for element itself, so your buttons behave like normal div (display: block). If you want to use flex in your way even if it's inappropriate change it to display: inline-flex.
More precise information directly from specification:
flex -
This value causes an element to generate a flex container box that is block-level when placed in flow layout.
inline-flex - This value causes an element to generate a flex container box that is inline-level when placed in flow layout.
#IMPROVEMENT
You have a lot of code that is not needed.
You can achieve same result by:
.parent > div {
display: flex;
}
<div class="parent">
<div>
<button>butt1</button>
<button>butt7</button>
</div>
<div>
<button>butt2</button>
<button>butt3</button>
<button>butt4</button>
<button>butt5</button>
<button>butt6</button>
</div>
</div>

If you want to apply a flex to the div1 do it like this:
.parent>.div1{
display: flex;
}
See here, I've added a background color for you to see what's going on:
.parent {
background: red;
display: flex;
flex-direction: column;
}
.parent>.div1 {
background: blue;
margin: 10px;
display: flex;
}
.parent>div:nth-child(2) {
background: green;
margin: 10px;
display: flex;
}
<div class="parent">
<div class="div1">
<button>butt1</button><button>butt7</button>
</div>
<div class="div2">
<button>butt2</button><button>butt3</button><button>butt4</button>
<button>butt5</button><button>butt6</button>
</div>
</div>

this line of CSS is the issue:
.parent>div>button{
display: flex;
}
You are telling css CSS using > that rules will be applied to elements which are direct children of the .parent -> div -> button element.
.parent {
display: flex;
flex-direction: column;
}
.parent>div:nth-child(2) {
display: flex;
}
<div class="parent">
<div class="div1"><button>butt1</button><button>butt7</button></div>
<div class="div2"><button>butt2</button><button>butt3</button><button>butt4</button>
<button>butt5</button><button>butt6</button></div>
</div>

Related

Using Flexbox, how do you separate two items even after the row wraps? [duplicate]

I have a
<div class="parent">
<div class="child" style="float:right"> Ignore parent? </div>
<div> another child </div>
</div>
The parent has
.parent {
display: flex;
}
For my first child, I want to simply float the item to the right.
And my other divs to follow the flex rule set by the parent.
Is this something possible?
If not, how do I do a float: right under flex?
You can't use float inside flex container and the reason is that float property does not apply to flex-level boxes as you can see here Fiddle.
So if you want to position child element to right of parent element you can use margin-left: auto but now child element will also push other div to the right as you can see here Fiddle.
What you can do now is change order of elements and set order: 2 on child element so it doesn't affect second div
.parent {
display: flex;
}
.child {
margin-left: auto;
order: 2;
}
<div class="parent">
<div class="child">Ignore parent?</div>
<div>another child</div>
</div>
You don't need floats. In fact, they're useless because floats are ignored in flexbox.
You also don't need CSS positioning.
There are several flex methods available. auto margins have been mentioned in another answer.
Here are two other options:
Use justify-content: space-between and the order property.
Use justify-content: space-between and reverse the order of the divs.
.parent {
display: flex;
justify-content: space-between;
}
.parent:first-of-type > div:last-child { order: -1; }
p { background-color: #ddd;}
<p>Method 1: Use <code>justify-content: space-between</code> and <code>order-1</code></p>
<div class="parent">
<div class="child" style="float:right"> Ignore parent? </div>
<div>another child </div>
</div>
<hr>
<p>Method 2: Use <code>justify-content: space-between</code> and reverse the order of
divs in the mark-up</p>
<div class="parent">
<div>another child </div>
<div class="child" style="float:right"> Ignore parent? </div>
</div>
Use justify-content: flex-end; in parent:
display: flex;
width: 100%;
flex-wrap: wrap;
justify-content: flex-end;
more info
display: flex;
flex-wrap: wrap;
justify-content: space-between;

CSS flex space-between issue

I have a unique problem where I want the link elements inside a div to use flex space-between BUT these links open up modal layers and the modal div is actually within the parent div. Now just having this empty div in the #parent div is causing additional spacing. How can I resolve this? By the way ... I cannot reorganize the markup ... the modal divs have to be within the parent div.
So something like this:
#parent {
display: flex;
flex-direction: row;
justify-content: space-between;
}
#parent a {
max-width: 46px;
margin: 0 1%;
}
<div id="parent">
LINK 1
LINK 2
LINK 3
<div id="modal1" class="modal"></div>
<div id="modal2" class="modal"></div>
<div id="modal3" class="modal"></div>
</div>
I presume the modals will be full screen & hidden by default? If so:
.modal {
position: fixed;
display: none;
}

Center vertically and horizontally while obeying html rules with flexbox

I'm trying to make something similar to Bootstraps jumbotron class using flexbox. I want everything to be centered vertically and horizontally, but I want anything inside of the box to still respect standard HTML rules. That is, if I make an <h1> and then an <h4> I want them to be on separate lines; however, with my current flexbox properties, that's not happening. See the example below -- it looks like titlesubtitle instead of title\nsubtitle
.Jumbotron {
height: 300px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
<div class="Jumbotron">
<h1>title</h1>
<h4>subtitle</h4>
</div>
You can introduce a new, non-flex parent to wrap those elements, so that parent will be the centered flex-child, and it's children will just be normal, non-flex children
.Jumbotron {
height: 300px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
<div class="Jumbotron">
<div>
<h1>title</h1>
<h4>subtitle</h4>
</div>
</div>
Or for your example, if you just want the children of the flex parent to be on their own line, use flex-direction: column;
.Jumbotron {
height: 300px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
flex-direction: column;
}
<div class="Jumbotron">
<h1>title</h1>
<h4>subtitle</h4>
</div>

flex basis not applied when two divs containing the element

I have an input element which I want to grow and shrink using flex shrink but its flex-basis size is not being applied.
Here is my html:
<div class="flex-container">
<div class="flex-row">
<input type="text" name="query" class="searchbar" />
</div>
<div>
and my css:
.flex-container{
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
}
.flex-row input { flex: 0 1 450px; }
why is the basis size not being applied? it is getting set to a much smaller width than 450px.
Here is a fiddle with the example.
Actually what is happening here is that your input's immediate parent .flex-row is a simple div with no css properties and also not set to be a flex container hence it's width is auto and wrapping around the input and not applying the flex properties. To apply flex properties to the input use the following css to make the input's parent display be flex.
.flex-container{
display: flex;
}
.flex-row {
display: flex;
flex:1;
align-items: center;
justify-content: center;
}
.flex-container input { flex: 0 1 450px; }
Hope this helps.

Vertically justify content

Hopefully this isn't an unsolved task, but I'm trying to vertically justify an unknown (ish) number of divs inside of a container.
Each div should be equal distances from each other, and, additionally, the same distance from the edges. (Assuming the last part can be accomplished using ghost elements before and after)
The divs will each fill the width of the container, and the container is a set height, but the number of elements inside the container is unknown.
I'm assuming it can be done using Flexbox to some degree, but have been unsuccessful in my attempts thus far.
Yep, flexbox is the simplest way to do it.
On the container element:
.container {
display: flex;
flex-direction: column;
justify-content: space-between;
}
On the child elements:
.container div {
flex: 1;
width: 100%
}
For the spacing between the elements, just add padding to the container and bottom margins to the children.
The style would look like this:
.container {
/* Same as above, and */
padding: 20px;
}
.container div {
/* Same as above, and */
margin-bottom: 20px;
}
.container div:last-of-type{
margin-bottom: 0;
/* So that spacing is even at bottom and top of container */
}
(I was typing this when you posted your answer, so I put it up anyway)
Fiddle
I use justify-content:space-evenly.
HTML:
div.container {
display: flex;
}
div.one_item_container {
display: flex;
flex-direction: column;
justify-content: space-evenly;
}
<div class="container">
<div class="one_item_container">
<img height="30" src="hello.jpeg" style="background-color:lightblue;" />
</div>
<div class="one_item_container">
<img height="50" src="hello2.jpeg" style="background-color:lightblue;" />
</div>
<div class="one_item_container">
<img height="40" src="hello2.jpeg" style="background-color:lightblue;" />
</div>
</div>
As usual, no matter how long I search, I find the answer only immediately after I ask the question. :D
For those curious, or for my own future reference: Flexbox's justify DOES work, you just need a few more options:
HTML:
<div id="outer-container">
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
</div>
CSS:
#outer-container {
height: 250px;
width: 200px;
background: red;
display: flex;
justify-content: space-around;
flex-direction: column;
}
.inner-element {
width: 200px;
height: 10px;
background: blue;
}
https://css-tricks.com/almanac/properties/j/justify-content/
https://jsfiddle.net/WW3bh/