Why does my header center its children vertically? [duplicate] - html

This question already has answers here:
How to disable equal height columns in Flexbox?
(4 answers)
Closed 1 year ago.
I am having trouble understanding the default behavior of display: flex
Why does my header vertically centers its children when I only add display: flex to it.
I have not added align-items: center; to the header.
Is it because I assigned it height: 100px;?
header {
display: flex;
border: 1px solid black;
height: 100px;
}
header div {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
max-width: 1224px;
margin: 0 auto;
}
nav a:not(:last-child) {
margin-right: 55px;
}
<header>
<div>
Link
<nav>
one
two
three
</nav>
Link
</div>
</header>
I am aware that the div has display: flex and align-items: center; But why does the parent html element header also need display: flex for its children to vertically center?

When you apply display: flex to the parent div, its children "stretch" to assume the full height and width of the container, since the default align-items property is stretch.
Hence, the child of the header now has a height of 100px (previously the height of its content), and the content is centered.
Your solution (to apply height: 100%) works since the content's height is now 100px (the height of the container), essentially simulating flexbox's vertical stretch.

It is not aligning vertically the header, it is aligning vertically the div inside the header.
Your header > div has display:flex and align-items: center which is explicit telling the div to align items to the center.

You don't need display: flex; on parents with only one child.
Your <header> tag has 100px of height and by default your <div> has implicit align-self: stretch; which is like you do height: 100% on it. For solving your problem you have two options:
Remove display: flex; from your <header> tag.
Asign align-self: flex-start; to your <div>.
Apply these two options to the <div> children for achieve the same results if you consider. The main key of this answer is: All children of a flex container has an implicit align-self: stretch by default.

Related

While using flex (column) for parent, Auto margin shrinks the child div [duplicate]

This question already has answers here:
How can I center text (horizontally and vertically) inside a div block?
(27 answers)
Closed 2 years ago.
I am trying to horizontally center one div inside parent div (Which is display flex in column mode) using margin 0 auto. When I do this the inner div is getting shrinked to the size of its content. Can someone explain why this is happening and how to fix this?
HTML
<div class="container">
<div class="mydiv">
CENTER THIS DIV
</div>
</div>
CSS
.container{
background-color: brown;
height: 100px;
display: flex;
flex-direction: column;
}
.mydiv{
background-color: chartreuse;
max-width: 500px;
margin: 0 auto;
}
If I remove flex from parent, then I am getting the correct output :
However, with the flex properties as in above code, this is what I get :
When you use display: flex; in a parent, the children automatically get the default flex values:
The item is sized according to its width and height properties. It shrinks to its minimum size to fit the container, but does not grow to absorb any extra free space in the flex container. This is equivalent to setting "flex: 0 1 auto".
That's why your .mydiv adjusts to fit the text.
(more info: https://developer.mozilla.org/en-US/docs/Web/CSS/flex)
If you don't want that to happen you could do something like this:
.container{
background-color: brown;
height: 100px;
display: flex;
flex-direction: column;
align-items: center; /* add this */
}
.mydiv{
background-color: chartreuse;
width: 100%; /* add this */
max-width: 500px; /* add this */
}
Working example:
https://codepen.io/sergiofruto/pen/dyMqbrm

How do I align inline element to the side of a centered div with 50vw so that it resizes properly?

I have a div that is set to be 50% of the page's width at all times, and is centered.
I would like to add an element to it's side so that the element touches the div's left edge (on different screen sizes). The element has a fixed max-width.
I've tried:
#element {
position: absolute;
align: left;
padding-left: 3vw;
}
It works on most common screen sizes, but as I go very small or very big the element either overlaps with the div or there is a gap. What I would like ideally would be for the element to stick to the side of the div.
Absolute positioning is very problematic for this kind of layout. I recommend a flexbox layout.
In order to achieve this layout we will need to add a couple divs. One div to act as the 3rd column, I gave it the class ghost because it will contain nothing although the demo here uses a red border so you can see it.
The other div I added wraps the special element you want to stick to the middle div. This is so the element wrapper (.element-wrap) is a flex child, not the element itself.
Next, give the container of these 3 divs display: flex, turning it into a flexbox container:
section {
display: flex;
align-items: center; /* vertical alignment */
justify-content: center; /* horizontal alignment */
}
The align-items property allows you to vertically align the items inside, while justify-content allows you to align them horizontally.
The center div, which I gave a blue background, will of course be in the middle of the layout and maintains its width with width: 50vw;. The 2 divs on the side have a class applied .flex-child which get this CSS:
.flex-child {
flex-grow: 1;
flex-basis: calc((100% - 50vw) / 2);
}
flex-grow: 1 allows those side divs to expand with the size of the screen. The flex-basis rule determines the starting size, where I am using a calc() function to dynamically calculate the width.
Now, the special element with the yellow background needs to be positioned next to the blue background, which is achieved here by turning its wrapper div into a flexbox too and aligning the content to the right:
.element-wrap {
display: flex;
justify-content: flex-end;
}
* { box-sizing: border-box; }
section {
display: flex;
align-items: center;
justify-content: center;
/* just for demo */
background: #eee;
}
.flex-child {
flex-grow: 1;
flex-basis: calc((100% - 50vw) / 2);
/* just for demo */
border: 1px solid red;
}
.half-screen {
width: 50vw;
min-height: 300px;
background: dodgerblue;
}
.element-wrap {
display: flex;
justify-content: flex-end;
}
.element {
/* just for demo */
background: yellow;
}
<section>
<div class="flex-child element-wrap">
<div class="element">
ELEMENT that we are<br>
getting to stick to the side<br>
of the 50vw div.
</div>
</div>
<div class="half-screen">
50vw DIV
</div>
<div class="flex-child ghost"><!-- nothing here --></div>
</section>

Flex direction elements width [duplicate]

I have a container <div> with display: flex. It has a child <a>.
How can I make the child appear "inline"?
Specifically, how can I make the child's width determined by its content, and not expand to the width of the parent?
What I tried:
I set the child to display: inline-flex, but it still took up the full width. I also tried all other display properties, but nothing had an effect.
Example:
.container {
background: red;
height: 200px;
flex-direction: column;
padding: 10px;
display: flex;
}
a {
display: inline-flex;
padding: 10px 40px;
background: pink;
}
<div class="container">
Test
</div>
http://codepen.io/donpinkus/pen/YGRxRY
Use align-items: flex-start on the container, or align-self: flex-start on the flex items.
No need for display: inline-flex.
An initial setting of a flex container is align-items: stretch. This means that flex items will expand to cover the full length of the container along the cross axis.
The align-self property does the same thing as align-items, except that align-self applies to flex items while align-items applies to the flex container.
By default, align-self inherits the value of align-items.
Since your container is flex-direction: column, the cross axis is horizontal, and align-items: stretch is expanding the child element's width as much as it can. (The column setting is also the reason why display: inline-flex isn't working.)
You can override the default with align-items: flex-start on the container (which is inherited by all flex items) or align-self: flex-start on the item (which is confined to the single item).
Learn more about flex alignment along the cross axis here:
How does flex-wrap work with align-self, align-items and align-content?
Learn more about flex alignment along the main axis here:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
In addition to align-self you can also consider auto margin which will do almost the same thing
.container {
background: red;
height: 200px;
flex-direction: column;
padding: 10px;
display: flex;
}
a {
margin-right:auto;
padding: 10px 40px;
background: pink;
}
<div class="container">
Test
</div>
width: min-content also yields the same result.
Not supported in IE11 if that matters to you: https://caniuse.com/mdn-css_properties_width_min-content

Make flex items take content width, not width of parent container

I have a container <div> with display: flex. It has a child <a>.
How can I make the child appear "inline"?
Specifically, how can I make the child's width determined by its content, and not expand to the width of the parent?
What I tried:
I set the child to display: inline-flex, but it still took up the full width. I also tried all other display properties, but nothing had an effect.
Example:
.container {
background: red;
height: 200px;
flex-direction: column;
padding: 10px;
display: flex;
}
a {
display: inline-flex;
padding: 10px 40px;
background: pink;
}
<div class="container">
Test
</div>
http://codepen.io/donpinkus/pen/YGRxRY
Use align-items: flex-start on the container, or align-self: flex-start on the flex items.
No need for display: inline-flex.
An initial setting of a flex container is align-items: stretch. This means that flex items will expand to cover the full length of the container along the cross axis.
The align-self property does the same thing as align-items, except that align-self applies to flex items while align-items applies to the flex container.
By default, align-self inherits the value of align-items.
Since your container is flex-direction: column, the cross axis is horizontal, and align-items: stretch is expanding the child element's width as much as it can. (The column setting is also the reason why display: inline-flex isn't working.)
You can override the default with align-items: flex-start on the container (which is inherited by all flex items) or align-self: flex-start on the item (which is confined to the single item).
Learn more about flex alignment along the cross axis here:
How does flex-wrap work with align-self, align-items and align-content?
Learn more about flex alignment along the main axis here:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
In addition to align-self you can also consider auto margin which will do almost the same thing
.container {
background: red;
height: 200px;
flex-direction: column;
padding: 10px;
display: flex;
}
a {
margin-right:auto;
padding: 10px 40px;
background: pink;
}
<div class="container">
Test
</div>
width: min-content also yields the same result.
Not supported in IE11 if that matters to you: https://caniuse.com/mdn-css_properties_width_min-content

CSS Center Image Horizontally Inline Dynamic Width Parent

I'm trying to center an image horizontally inside of a div that has a width of 100%. Currently I have two images on either side that will act as buttons that have a float: left; and float: right; property.
All of the solutions I have tried have said to make the image display: block but that won't allow me to have the buttons on either side.
Here is the Codepen Example of my current code. I'm trying to center the image that has the class mainimg within the div with the class main.
Any ideas of how I would center that image?
Use flexbox and change your CSS rule for .main like this:
.main {
display: flex;
justify-content: space-between;
background: black;
height: 550px;
}
display: flex; will distribute the three items across the width, justify-content: space-between; will make sure the outer items remain at the outside positions.
http://codepen.io/anon/pen/kkjjJa