Flexbox didnt vertically centered [duplicate] - css

This question already has answers here:
Flexbox: center horizontally and vertically
(14 answers)
Closed 2 years ago.
I am trying to make this as an example to learn:
https://i.ibb.co/m4qJmQz/image.png
my code doesn't center the boxes.How can I make it better?
I want to learn how to
**center vertically the columns' content
**add space between gray ">" and texts - apply space-around or space-between 's space amount, so apply automatic space; not padding or margin
my html file:
http://elementor.help.helvatica.com/flexbox.html
code:
<html>
<head>
<title>The Flexbox Example - Murat Deniz</title>
<meta content="">
<style></style>
</head>
<body>
<style>
.container {
display: flex;
justify-content: space-around;
align-items: center;
height: 100%;
}
.icon {
background-color: gray;
color: saddlebrown;
width: 100%;
text-align: center;
height: fit-content;
}
.sub-container {
border-color: gainsboro;
border-radius: 5px;
border-style: solid;
box-shadow: 0px 0px 30px 0px gainsboro;
display: flex;
justify-content: space-around;
width: 100%;
height: 100%;
}
li {
flex-direction: row;
display: flex;
}
ul {
padding-inline-start: unset;
}
.inline {
flex-direction: row;
display: flex;
}
.inline li:nth-child(3) {
align-content: flex-end;
color: red;
}
.main-container {
/** display: flex;
justify-content: space-around;
align-items: center; **/
height: 50%;
}
.section {
height: 100%;
}
</style>
<div class="main-container">
<div class="container">
<div class="section">
<p>Artboard</p>
<div class="sub-container">
<ul>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
<li>
<div class="icon">
</div>
<div class="text">
photo
</div>
</li>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
</ul>
</div>
</div>
<div class="section">
<p>Artboard Copy</p>
<div class="sub-container">
<ul class="inline">
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
<li>
<div class="icon">
</div>
<div class="text">
photo
</div>
</li>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
<li>
<div class="icon">
>
</div>
<div class="text">
video
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>

I think you can't put in-between space without using margin or padding as you are using 100% width. When you talk about automatic space you mean to use relative units of measure like .em or .vw

Related

How to make div expand with content using flex?

I have this HTML and CSS:
.container {
width: 100%;
}
.group {
display: flex;
justify-content: space-between;
min-width: 214px;
background: #eee;
}
.abbr {
/* some styling */
}
.name {
/* some styling */
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
</div>
Now, if I use just min-width, the whole div stretches as the entire width of the container. If I just use width, it won't expand if the name is longer than Mark Smith (rather it will go to the next line).
This is what I wanted to achieve:
How do I achieve this in flexbox?
What you're looking for is to apply width: fit-content to .group.
Then you can adjust the offset between the abbreviation and name with min-width on the .abbr.
This can be seen in the following:
.group {
display: flex;
width: fit-content;
background: #eee;
margin: 10px 0;
}
.group > div {
margin: 0 10px;
}
.abbr {
min-width: 50px;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">A Really Really Long Name</p>
</div>
</div>
</div>
I use inline-block on .container so that it won't take up the whole line.
.container {
display: inline-block;
}
.group {
display: flex;
background: #eee;
}
.abbr {
padding: 0 7px;
}
.name {
padding: 0 7px;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div>
<p class="name">Mark Smith</p>
</div>
</div>
</div><br/><br/>
<div class="container">
<div class="group">
<div class="abbr">
<p>MR</p>
</div>
<div>
<p class="name">Loooooooooooooooong Name</p>
</div>
</div>
</div>
Another solution is to use a third element that consume all the remaining space and set the background color on the text content only:
.container {
margin: 0 0 5px 0;
}
.group {
display: flex;
}
.abbr {
padding: 0 7px;
background: #eee;
}
.name {
padding: 0 7px;
background: #eee;
flex: 0 0 auto;
}
.blank-space{
flex: 1 1 auto;
}
<div class="container">
<div class="group">
<div class="abbr">
<p>MS</p>
</div>
<div class="name">
<p>Mark Smith</p>
</div>
<div class="blank-space"></div>
</div>
</div>
<div class="container">
<div class="group">
<div class="abbr">
<p>MR</p>
</div>
<div class="name">
<p>Loooooooooooooooong Name</p>
</div>
<div class="blank-space"></div>
</div>
</div>

Is it possible to set the width of siblings elements based from the longest element in css

I have a request to set the width of buttons to the longest sibling in a row of buttons.
Rules:
Buttons sit in columns of a row
Button content dictate the width of button.
The longest button should set other sibling button's width
I've tried using flex: 1 with max/min-width however this will break rule 2. And I can easily do this in js I'm wondering if possible in css alone?
https://codepen.io/matthewharwood/pen/JvoVzE?editors=1100
.link {
height: 49px;
padding: 0 24px;
margin-right: 20px;
background: pink;
a {
display: flex;
align-items: center;
line-height: 49px;
justify-content: center;
}
}
.container {
width: 70%;
margin: 0 auto;
background: papayawhip;
padding: 30px;
display: flex;
}
.container2 {
width: 70%;
margin: 0 auto;
background: orange;
padding: 30px;
display: flex;
flex-wrap: wrap;
}
.container3 {
width: 70%;
margin: 0 auto;
background: honeydew;
padding: 30px;
display: flex;
flex-wrap: wrap;
}
<div class="container">
<div class="link">
<span> 1 button</span>
</div>
<div class="link">
<span> secondary button</span>
</div>
</div>
<div class="container2">
<div class="link">
<span> 1 button</span>
</div>
<div class="link">
<span> secondary button</span>
</div>
<div class="link">
<span> third button</span>
</div>
</div>
<div class="container3">
<div class="link">
<span> 1 button</span>
</div>
<div class="link">
<span> 2 button</span>
</div>
</div>
Important Notice: the solution below is a hack.
The idea here is to rely on direction column and inline-flex to have all element equal width (the longest one) then I use transformation in order to revert back the row direction.
I know it's a bad hack
.link {
height: 49px;
padding: 0 24px;
background: pink;
border:1px solid;
}
.container {
padding: 30px;
display: inline-flex;
flex-wrap:wrap;
flex-direction:column;
}
.link:nth-child(2) {
transform:translate(100%,-100%);
}
.link:nth-child(3) {
transform:translate(200%,-200%);
}
.link:nth-child(4) {
transform:translate(300%,-200%);
}
<div class="container">
<div class="link">
<span> 1 button</span>
</div>
<div class="link">
<span> secondary button</span>
</div>
</div>
<br>
<div class="container">
<div class="link">
<span> 1 button</span>
</div>
<div class="link">
<span> secondary button</span>
</div>
<div class="link">
<span> third button</span>
</div>
</div>
<br>
<div class="container">
<div class="link">
<span> 1 button</span>
</div>
<div class="link">
<span> 2 button</span>
</div>
</div>

Flex Row space between wrapped items

What is the most dynamic way of having any amount of rows with any amount of items with a set margin between all the items? Right now the only thing that works for me is to wrap each item in a wrapper set the flex basis to the wrapper and the margin to the child. The issues with this is I loose the ability to have each row the same height of the tallest content in the row.
Case 1: Only margin bottom
https://jsfiddle.net/6oaney4e/6/
This works well because the content keep the height of the tallest item on each row
html
<div class="wrapper">
<div class="item">
text
</div>
<div class="item">
text
<br>
line2
</div>
<div class="item">
text
</div>
<div class="item">
text
</div>
</div>
css
.wrapper{
display: flex;
flex-flow: row wrap;
margin: -10px;
padding: 10px;
background: green;
}
.item{
flex: 0 0 50%;
background: orange;
margin-bottom: 10px;
}
Case 2: All around margin
https://jsfiddle.net/6oaney4e/7/
Here for some reason the rows break I'm guessing that's because the row cant fit the items in with the extra margin on the side.
html same as CASE 1
css
.wrapper{
display: flex;
flex-flow: row wrap;
margin: -10px;
padding: 10px;
background: green;
}
.item{
flex: 0 0 50%;
background: orange;
margin: 10px;
}
Case 3: Wrapping items and adding margin to the inner item
https://jsfiddle.net/6oaney4e/8/
That worked but now the items on each row arent really aware of each other and cant have the same height.
html
<div class="wrapper">
<div class="item-wrap">
<div class="item">
text
</div>
</div>
<div class="item-wrap">
<div class="item">
text
<br>
line2
</div>
</div>
<div class="item-wrap">
<div class="item">
text
</div>
</div>
<div class="item-wrap">
<div class="item">
text
</div>
</div>
</div>
css
.wrapper{
display: flex;
flex-flow: row wrap;
margin: -10px;
padding: 10px;
background: green;
}
.item-wrap{
flex: 0 0 50%;
}
.item{
background: orange;
margin: 10px;
}
Is there a way to keep the HTML as in CASE 1 (without the div.item-wrap), have the items on each row the same height as in CASE 1 and have the spacing work like in CASE 3?
Ideally, you do want to use rows and make the .item-wrap divs flex-parents too.
.wrapper {
display: flex;
flex-flow: row wrap;
margin: -10px;
padding: 10px;
background: green;
}
.item-wrap {
flex: 0 0 50%;
display: flex;
}
.item {
background: orange;
margin: 10px;
flex: 1;
}
<div class="wrapper">
<div class="item-wrap">
<div class="item">
text
</div>
</div>
<div class="item-wrap">
<div class="item">
text
<br> line2
</div>
</div>
<div class="item-wrap">
<div class="item">
text
<br> line2
<br> line3
</div>
</div>
<div class="item-wrap">
<div class="item">
text
</div>
</div>
</div>
However if you must retain the existing structure, you'll need to use calc to adjust the flex-basis. Something like this:
.wrapper {
display: flex;
flex-flow: row wrap;
background: green;
justify-content: space-between;
}
.item {
flex-grow:0;
flex-shrink:0;
flex-basis:calc(50% - 10px); /* separate properties for IE11 upport */
background: orange;
margin: 5px;
}
<div class="wrapper">
<div class="item">
text
</div>
<div class="item">
text
<br> line2
</div>
<div class="item">
text
<br> line2
<br> line3
</div>
<div class="item">
text
</div>
</div>

flexbox height adjust to content

I use a "full design" flexbox.
I have a weird issue : I have a container that takes all the remaining space and I want in this container that the child, which is also flexbox, to have their height adjust to their content.
Here is the issue:
body, html {
width:100%;
height:100%;
display:flex;
}
.container {
display:flex;
flex:1;
flex-wrap:wrap;
}
.icon {
width:10vh;
margin:10px;
display:flex;
flex-direction:column;
}
.img {
width:10vh;
height:10vh;
display:flex;
align-items:center;
justify-content:center;
background-color:red;
}
.text {
text-align:center;
}
<div class="container">
<div class="icon">
<div class="img">
</div>
<div class="text">
action 1
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 2
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 3
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 4
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 5
</div>
</div>
</div>
As you can see, the icon takes the full height of the container : in fact, I don't want to specify a height because I don't know the text length and really want that, if the content is huge, the icon takes the height of its content ( don't want to cut the text). Moreover, if the page is resized, I really want the icon to be aligned (like on smartphone).
Also, I don't understand why the icon takes the height of its parent and not its content because I didn't specify "flex:1" on it. I assume that the default behaviour it's to fit the content size, but this seems not to be working.
image of the issue
.icon's are flex-column which makes .img's stretch by default unless .icon's have align-items. The reason why I didn't apply align-items to .icon's is because other nested flex-containers/flex-items started collapsing. Instead of adjusting down through the hierarchy, I went up and adjusted .container instead.
The relevant CSS:
.container {
display: flex;
flex: 1; /* If you remove this .container will shrink to wrap around .icon's */
flex-wrap: wrap;
justify-content: center; /* This centers .icon's along a horizontal axis. */
align-items: baseline; /* This aligns .icon's along a common baseline vertically. */
outline: 3px dashed blue; /* To show the size of .container */
}
.icon {
width: 10vh;
margin: 10px;
display: flex;
flex-direction: column;
outline: 1px dashed red; /* To show the size of .icon */
}
body,
html {
width: 100%;
height: 100%;
display: flex;
}
.container {
display: flex;
flex: 1;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
align-content: flex-start;
outline: 3px dashed blue;
}
.icon {
width: 10vh;
margin: 10px;
display: flex;
flex-direction: column;
outline: 1px dashed red;
}
.img {
width: 10vh;
height: 10vh;
display: flex;
align-items: center;
justify-content: center;
background-color: red;
}
.text {
text-align: center;
}
<div class="container">
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 1
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 2
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 3
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 4
</div>
</div>
<div class="icon">
<div class="img">
</div>
<div class="text">
Action 5
</div>
</div>
</div>

Center last row element using Flexbox

When I resize the window to smaller resolution I would like the last element to be centered. I know that I can achive that by setting parent's justify-content parameter to space-around or center, but it has to be set to: space-between.
ul {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
background: rgba(255, 0, 0, 0.3);
padding: 0;
}
li {
list-style-type: none;
display: inline-block;
min-width: 100px;
height: 100px;
background: red;
margin: 10px;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
http://jsfiddle.net/k7fzdn80/
use auto margin
margin: 10px auto;
is this what you expect?
Solution
Unfortunately, it is not possible with flexbox for your problem. But I have a CSS hack to solve the issue. Target the last element within the media-query. I have used custom breakpoints below.
ul {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
background: rgba(255, 0, 0, 0.3);
padding: 0;
}
li {
list-style-type: none;
display: inline-block;
min-width: 100px;
height: 100px;
background: red;
margin: 10px;
}
#media (min-width: 376px) and (max-width: 494px) {
li:last-child {
margin: 10px auto;
}
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
It's not possible. space-between definition says
If [...] there is only a single flex item on the line, this value
is identical to 'flex-start'.
The only way would be doing the alignment manually, e.g. with media queries and auto margins. But then the layout won't be flexible at all.
I have another proposal. Using the calc() to calculate the width of the flex item. And so the last element could be centered.
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
width: 100%;
row-gap: 10px;
}
.column {
display: flex;
width: calc(100% / 4);
overflow: hidden;
text-align: center;
background: green;
}
.inside-column {
background: white;
width: 100%;
display: block;
margin: 15px;
border: 5px solid red;
}
.wrap {
max-width: 350px;
background: #CCC;
}
<div class="container">
<div class="column">
<a href="#" class="inside-column">
1
<br>Content Content Content
</a>
</div>
<div class="column">
<div class="inside-column">
2
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
3
</div>
</div>
<div class="column">
<div class="inside-column">
4
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
5
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
6
</div>
</div>
<div class="column">
<div class="inside-column">
7
</div>
</div>
<div class="column">
<div class="inside-column">
8
</div>
</div>
<div class="column">
<div class="inside-column">
9
</div>
</div>
</div>
<br>
<br>
<div class="wrap">
<div class="container">
<div class="column">
<a href="#" class="inside-column">
1
<br>Content Content Content
</a>
</div>
<div class="column">
<div class="inside-column">
2
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
3
</div>
</div>
<div class="column">
<div class="inside-column">
4
<br>Content Content Content
</div>
</div>
<div class="column">
<div class="inside-column">
5
</div>
</div>
<div class="column">
<div class="inside-column">
6
</div>
</div>
<div class="column">
<div class="inside-column">
7
</div>
</div>
<div class="column">
<div class="inside-column">
8
</div>
</div>
<div class="column">
<div class="inside-column">
9
</div>
</div>
</div>
</div>

Resources