centering flex items vertically and side by side at same level - css

I have been trying to centering the the flex items vertically but with that I also want them side by side at same level
tried:
1)to parent block
display:flex;
align-items:center;
but it doesn't make it at same level (my content to second flex item will not be the same in length), required some generic solution
2)padding top and bottom
as (my content to second flex item will not be the same in length) requirement not satisfy, it doesn't work either
Its currently use with grid, but as IE11 doesnt support grid, I'm converting into flex
please review the codepen after applying align-items to flex
codepen with grid
ref-image expected output

Well you can't do that with flexbox since you have aligned the items to the center which overrides the height equalisation of align-items:stretch
Your only option is to wrap those elements in a separate div and center that.
.main {
display: flex;
align-items: center;
background-color: orange;
height: 200px;
margin: 0 auto;
width: 500px;
}
.inner {
display: flex;
}
.item {
display: flex;
border: 1px solid;
}
.one {
margin-right: 15px;
}
.two {
max-width: 200px;
}
<div class="main">
<div class="inner">
<div class="item one">One</div>
<div class="item two">some text will be here and it will not defined against its length</div>
</div>
</div>

Related

How do I position a flex item at the top of a columnar flex-container, when the container is set to center-justify its children?

I have a flex-container with the 'flex-direction' set to column and 'justify-content' set to 'center'.
By default child items will be vertically aligned to the center of the flex-container.
However, I want the first item to be flush against the top of the column.
So for the child I've added the property 'justify-self: flex-start'.
This has no effect. The 'justify-self' property is being ignored.
[Codepen](https://codepen.io/bobdobbs_/pen/XWBNZwx)
Even when I set 'justify-self' to !important the property gets ignored.
The easiest thing to do here seems to be to use absolute positioning. But if that's the case there doesn't seem to be much of a point to using flexbox for anything much at all.
Is there a flexbox solution for this problem?
Or should I just stick to using absolute positioning?
I would separate the header content from the other content (for readability and semantic structuring of the column) and use flex to create two containing divs inside the parent (one for the header and one for the content) - and apply the vertical centering to the content area.
I have added outlines to show the different divs and aligned the text to the center of the column too.
.wrapper {
display:flex;
flex-direction: column;
outline: solid 1px red;
outline-offset: -1px;
width: 300px;
height: 100vh;
}
h2, p {margin: 0}
.header {
padding: 8px;
text-align: center;
flex-shrink:0;
outline: solid 1px blue;
outline-offset: -4px;
}
.content {
padding: 8px;
text-align: center;
flex-grow:1;
outline: solid 1px green;
outline-offset: -4px;
display:flex;
flex-direction: column;
justify-content: center;
}
<div class="wrapper">
<div class="header">
<h2>heading</h2>
</div>
<div class="content">
<p>content</p>
<p>content</p>
<p>content</p>
</div>
</div>
Please press "Run code snippet" and see the code. Stop useing position absolute for normal positioning things.
Use 1-2 hour here -> https://flexboxfroggy.com/ and you will be good at flexbox.
.flex {
display: flex;
}
.jcc {
justify-content: center;
align-items: center;
}
.column {
flex-direction: column;
}
<div class="flex jcc column">
<h2>I want this header to be at the top</h2>
<h3>let this be centered</h3>
</div>

Make an image shrink to available height without expanding its parent

I'm trying to create a two-column section where:
Columns have same width (responsive)
The height of block is defined by the height of image contained in left column after it stretches to 100% of it's parent.
In the right column there are several elements one of which is a link containing image.
I want that link with image from last paragraph to shrink it's height containing original image aspect ratio without stretching the it's container when the image has portrait orientation.
Not sure it its possible with plain CSS. Tried with flexbox and grid layout but I must be missing something.
I prepared a fiddle: https://jsfiddle.net/Kuznets/8u6c70ku/3/
* { box-sizing: border-box }
.wrap { max-width: 80%; margin: 0 auto; }
.container { display: flex; }
.left, .right {
flex: 0 0 50%;
border: 1px solid black;
}
.left {
position: relative;
display: flex;
align-items: flex-end;
}
.left div.left-text {
position: absolute;
color: white;
padding: 1em;
font-size: 200%;
}
.should-set-height {
width: 100%;
}
.right {
display: flex;
flex-direction: column;
align-items: center;
justify-content:space-between;
}
<div class="wrap">
<div class="container">
<div class="left">
<img class="should-set-height" src="https://dummyimage.com/200x240/aaaaaa/ffffff" alt="">
<div class="left-text">
This is a beautiful slogan
</div>
</div><!--/.left-->
<div class="right">
<header>Product title</header>
<a class="fit-height" href="javascript:void(0)">
<img class="should-shrink" src="https://dummyimage.com/200x400/aaaaaa/ffffff">
</a>
<div class="price">$ 19.99</div>
<button class="button-black">Add to basket</button>
</div><!--/.right-->
</div><!--/.containter-->
</div><!--/.wrap-->
One way you could accomplish this would be to have the left image set to have width: 100%, height: auto; then use a background image for the right container.
Here's a quick demo on CodePen: https://codepen.io/patriziosotgiu/pen/NaBmZe?editors=1100
You could also add extra rules, like for instance a min-width for the left column, or have those columns fit in one column for mobile.
Note: I assumed the left image to be larger than 200x240px

Why does space-around allow flex items to overflow on the left side?

It seems that Chrome doesn't handle justify-content: space-around correctly when the content overflows the flex container, and the container is not set up to allow wrapping, but instead horizontal scrolling.
Some of the content overflows on the left side of the flex container, and is cut off. I want it to overflow on the right side, so that I can reach it by scrolling horizontally.
Here is an example:
#container {
display: flex;
width: 500px;
justify-content: space-around;
border: solid black;
overflow: auto;
}
.item {
min-width: 200px;
margin: 10px;
background-color: red;
display: table;
font-size: 48pt;
text-align: center;
}
<div id="container">
<div class="item">1</div><div class="item">2</div>
<div class="item">3</div><div class="item">4</div>
<div class="item">5</div><div class="item">6</div>
</div>
That's because when there isn't enough space, space-around behaves like center:
If the leftover free-space is negative or there is only a single flex
item on the line, this value is identical to center.
And center behaves like you describe:
If the leftover free-space is negative, the flex items will overflow
equally in both directions.
Instead, you can use space-between:
If the leftover free-space is negative or there is only a single flex
item on the line, this value is identical to flex-start.
Of course, then you won't have half-size spaces on neither end of the flex line. You can insert pseudo-element to have full-size spaces, though.
#container {
display: flex;
justify-content: space-between; /* Instead of space-around */
}
#container::before, #container::after {
content: ''; /* Insert space before the first item and after the last one */
}
.container {
display: flex;
width: 500px;
border: solid black;
justify-content: space-between;
overflow: auto;
margin: 10px 0;
}
.container::before, .container::after {
content: '';
}
.item {
margin: 10px;
background-color: red;
display: table;
font-size: 48pt;
text-align: center;
}
.big > .item {
min-width: 200px;
}
<div class="container big">
<div class="item">1</div><div class="item">2</div>
<div class="item">3</div><div class="item">4</div>
<div class="item">5</div><div class="item">6</div>
</div>
<div class="container">
<div class="item">1</div><div class="item">2</div>
<div class="item">3</div><div class="item">4</div>
<div class="item">5</div><div class="item">6</div>
</div>
Since the container is limited in width and you want overflowing flex items to be accessed via horizontal scrolling, why use justify-content: space-around?
Try justify-content: flex-start:
Revised Codepen
To understand why overflowing flex items may be inaccessible via scroll, see this answer.
If you're interested in a Javascript workaround for the original code, see this post:
When centering horizontally, li's get cut off

How to justify a single flexbox item (override justify-content) [duplicate]

This question already has answers here:
In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?
(6 answers)
Closed 1 year ago.
You can override align-items with align-self for a flex item.
I am looking for a way to override justify-content for a flex item.
If you had a flexbox container with justify-content:flex-end, but you want the first item to be justify-content: flex-start, how could that be done?
There doesn't seem to be justify-self, but you can achieve similar result setting appropriate margin to auto¹. E. g. for flex-direction: row (default) you should set margin-right: auto to align the child to the left.
.container {
height: 100px;
border: solid 10px skyblue;
display: flex;
justify-content: flex-end;
}
.block {
width: 50px;
background: tomato;
}
.justify-start {
margin-right: auto;
}
<div class="container">
<div class="block justify-start">justify-start</div>
<div class="block"></div>
</div>
¹ This behaviour is defined by the Flexbox spec.
AFAIK there is no property for that in the specs, but here is a trick I’ve been using:
set the container element ( the one with display:flex ) to justify-content:space-around
Then add an extra element between the first and second item and set it to flex-grow:10 (or some other value that works with your setup)
Edit: if the items are tightly aligned it's a good idea to add flex-shrink: 10; to the extra element as well, so the layout will be properly responsive on smaller devices.
If you aren't actually restricted to keeping all of these elements as sibling nodes you can wrap the ones that go together in another default flex box, and have the container of both use space-between.
.space-between {
border: 1px solid red;
display: flex;
justify-content: space-between;
}
.default-flex {
border: 1px solid blue;
display: flex;
}
.child {
width: 100px;
height: 100px;
border: 1px solid;
}
<div class="space-between">
<div class="child">1</div>
<div class="default-flex">
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
</div>
</div>
Or if you were doing the same thing with flex-start and flex-end reversed you just swap the order of the default-flex container and lone child.
I solved a similar case by setting the inner item's style to margin: 0 auto.
Situation: My menu usually contains three buttons, in which case they need to be justify-content: space-between. But when there's only one button, it will now be center aligned instead of to the left.
For those situations where width of the items you do want to flex-end is known, you can set their flex to "0 0 ##px" and set the item you want to flex-start with flex:1
This will cause the pseudo flex-start item to fill the container, just format it to text-align:left or whatever.
To expand on Pavlo's answer https://stackoverflow.com/a/34063808/1069914, you can have multiple child items justify-content: flex-start in their behavior but have the last item justify-content: flex-end
.container {
height: 100px;
border: solid 10px skyblue;
display: flex;
justify-content: flex-end;
}
.container > *:not(:last-child) {
margin-right: 0;
margin-left: 0;
}
/* set the second to last-child */
.container > :nth-last-child(2) {
margin-right: auto;
margin-left: 0;
}
.block {
width: 50px;
background: tomato;
border: 1px solid black;
}
<div class="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block" style="width:150px">I should be at the end of the flex container (i.e. justify-content: flex-end)</div>
</div>

How can I horizontally align my divs?

For some reason my divs won't center horizontally in a containing div:
.row {
width: 100%;
margin: 0 auto;
}
.block {
width: 100px;
float: left;
}
<div class="row">
<div class="block">Lorem</div>
<div class="block">Ipsum</div>
<div class="block">Dolor</div>
</div>
And sometimes there is a row div with just one block div in it. What am I doing wrong?
To achieve what you are trying to do:
Consider using display: inline-block instead of float.
Try this:
.row {
width: 100%;
text-align: center; // center the content of the container
}
.block {
width: 100px;
display: inline-block; // display inline with ability to provide width/height
}​
DEMO
having margin: 0 auto; along with width: 100% is useless because you element will take the full space.
float: left will float the elements to the left, until there is no space left, thus they will go on a new line. Use display: inline-block to be able to display elements inline, but with the ability to provide size (as opposed to display: inline where width/height are ignored)
Alignments in CSS had been a nightmare. Luckily, a new standard is introduced by W3C in 2009: Flexible Box. There is a good tutorial about it here. Personally I find it much more logical and easier to understand than other methods.
.row {
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
}
.block {
width: 100px;
}
<div class="row">
<div class="block">Lorem</div>
<div class="block">Ipsum</div>
<div class="block">Dolor</div>
</div>
Using FlexBox:
<div class="row">
<div class="block">Lorem</div>
<div class="block">Ipsum</div>
<div class="block">Dolor</div>
</div>
.row {
width: 100%;
margin: 0 auto;
display: flex;
justify-content: center; /* for centering 3 blocks in the center */
/* justify-content: space-between; for space in between */
}
.block {
width: 100px;
}
The latest trend is to use Flex or CSS Grid instead of using Float. However, still some 1% browsers don't support Flex. But who really cares about old IE users anyway ;)
Fiddle: Check Here
Another working example, using display: inline-block and text-align: center
HTML:
<div class='container'>
<div class='row'>
<div class='btn'>Hello</div>
<div class='btn'>World</div>
</div>
<div class='clear'></div>
</div>
CSS:
.container {
...
}
.row {
text-align: center;
}
.btn {
display: inline-block;
margin-right: 6px;
background-color: #EEE;
}
.clear {
clear: both;
}
Fiddle: http://jsfiddle.net/fNvgS/
Although not covering this question (because you want to align the <div>s inside the container) but directly related: if you wanted to align just one div horizontally you could do this:
#MyDIV
{
display: table;
margin: 0 auto;
}
If elements are to be displayed in one line and IE 6/7 do not matter, consider using display: table and display: table-cell instead of float.
inline-block leads to horizontal gaps between elements and requires zeroing that gaps. The most simple way is to set font-size: 0 for parent element and then restore font-size for child elements that have display: inline-block by setting their font-size to a px or rem value.
I tried the accepted answer, but eventually found that:
margin: 0 auto;
width: anything less than 100%;
Works well so far.
I've use this two approaches when I need to handle horizontal div alignment.first (Center Aligning Using the margin Property):
.center-horizontal-align {
margin-left: auto;
margin-right: auto;
width: (less than 100%) or in px
}
Setting the left and right margins to auto specifies that they should split the available margin equally. Center-aligning has no effect if the width is 100%.
and the second:
.center-horizontal-align {
display: table
margin-left: auto;
margin-right: auto;
}
Using the second approach is convenient when you have several elements and you want all of them to be centred in one table cell(i.e. several buttons in one cell).
instead of float use flex
.row {
display: flex;
flex-direction: row;
}

Resources