I'm using FlexBox to create a basic Purchase Form, the simplified code is in the below CodePen.
The Code Pen
The Flex Item in question are those with:
class="purchase_body_checkout_form_selectable-product"
When I was testing it in my actual Project (with other items on the page), the results didn't happen until the 7th Flex Item was added, in the Code Pen you can see what I'm talking about after adding the 4th Flex Item.
You'll need to uncomment out the section of HTML I've commented out in the CodePen, there's 3 sections, each with some commentary.
What I'm talking about is that the Flex Container grows once I add the 4th or more Flex Item.
It grows even more after the 5th Flex Item, and continues to for the next few.
This DOES NOT happen when I use Grid, so I assume it has to do with Flex's "self-growth" nature.
I don't understand why this is.
When I tested this in my Development Environment, the Container remained the same size until the 7th Flex Item was added.
There was no difference between Items, I used React, each new Item is an exact replica of the others (I literally duplicated the React Element).
It currently doesn't make sense why the Container will grow after basically repeating what I did for the first Row, without any need to grow.
If the first Row was sized just fine, with 2 Flex Items (again, each Flex Item is coded the exact same from HTML to CSS), then why does the addition of another Row cause the Container to grow?
The second Row should have the same size requirements as the first Row... Right?
That is the confusion I wish to clear up. Any thoughts that could explain this behavior?
My guess is something to do with the Container of the Checkout AND Summary sections of the Purchase Form. Since I have "justify-content: space-between", and something about the 4th Flex Item requires slightly more space, that causes the (Checkout) Container to expand more (since it has that space, via the "space-between" gap being fairly large.
I'm still fairly new to Flex Box, so please try to address any assumptions or ignorances you notices in my explanation above.
Thank you! (:
In summary:
Tried adding Flex Items to Flex Container, expected after the first Row, the size requirements would be the same for the second Row (each Flex Item is identical), but yet, the second Row causes the Flex Container to grow in size.
Here's the CSS (Code Pen has it in a cleaner format):
`
body {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 25%;
gap: 100px;
background-color: gray;
}
.purple-blue { background-color: #5100FF }
.purchase_body_checkout_container {
display: flex;
flex-wrap: wrap;
width: 100%;
justify-content: space-between;
align-items: flex-start;
gap: 25px;
}
.purchase_body_checkout_form,
.purchase_body_checkout_order-summary {
padding: 12px;
border-radius: 12px;
background-color: white;
}
.purchase_body_checkout_form_product-selection {
display: flex;
flex-wrap: wrap;
}
.purchase_body_checkout_form_selectable-product {
position: relative;
color: white;
display: flex;
align-items: center;
justify-content: center;
flex: 1 1 50%;
max-width: 50%;
overflow: hidden;
}
`
Basic HTML Structure is the following (see CodePen for the Comments I mentioned above to add the 4th+ Flex Item to see the Container grow)
This only has a single Flex Item, to keep it concise (CodePen has the rest):
<div class="purchase_body_checkout_container">
<div class="purchase_body_checkout_form">
<h2 class="purchase_body_checkout_form_header">Checkout</h2>
<div class="purchase_body_checkout_form_product-selection">
<div class="purchase_body_checkout_form_selectable-product">
<input type="checkbox" class="purchase_body_checkout_form_selectable-product_checkbox" />
<h3 class="purchase_body_product_name purple-blue">TEST ONE</h3>
</div>
</div>
</div>
<div class="purchase_body_checkout_order-summary">
<h2 class="purchase_body_checkout_order-summary_header">Order Summary</h2>
</div>
</div>
As you can see from this screenshot, the .purchase_body_checkout_form is not already taking up its width potential, which is indicated by the shaded purple. This means with flex this container can grow and will grow into the space when the viewport expands.
The reverse is also true. You will notice if you shrink your codepen down to a mobile device the container has the desired spacing. I suggest putting a max-width on .purchase_body_checkout_form.
body {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 25%;
gap: 100px;
background-color: gray;
}
.purple-blue {
background-color: #5100FF
}
.purchase_body_checkout_container {
display: flex;
flex-wrap: wrap;
width: 100%;
justify-content: space-between;
align-items: flex-start;
gap: 25px;
}
.purchase_body_checkout_form,
.purchase_body_checkout_order-summary {
padding: 12px;
max-width: 280px;
border-radius: 12px;
background-color: white;
}
.purchase_body_checkout_form_product-selection {
display: flex;
flex-wrap: wrap;
}
.purchase_body_checkout_form_selectable-product {
position: relative;
color: white;
display: flex;
align-items: center;
justify-content: center;
flex: 1 1 50%;
max-width: 50%;
overflow: hidden;
}
<div class="purchase_body_checkout_container">
<div class="purchase_body_checkout_form">
<h2 class="purchase_body_checkout_form_header">Checkout</h2>
<div class="purchase_body_checkout_form_product-selection">
<div class="purchase_body_checkout_form_selectable-product">
<input type="checkbox" class="purchase_body_checkout_form_selectable-product_checkbox" />
<h3 class="purchase_body_product_name purple-blue">TEST ONE</h3>
</div>
<div class="purchase_body_checkout_form_selectable-product">
<input type="checkbox" class="purchase_body_checkout_form_selectable-product_checkbox" />
<h3 class="purchase_body_product_name purple-blue">TEST ONE</h3>
</div>
<div class="purchase_body_checkout_form_selectable-product">
<input type="checkbox" class="purchase_body_checkout_form_selectable-product_checkbox" />
<h3 class="purchase_body_product_name purple-blue">TEST ONE</h3>
</div>
<div class="purchase_body_checkout_form_selectable-product">
<input type="checkbox" class="purchase_body_checkout_form_selectable-product_checkbox" />
<h3 class="purchase_body_product_name purple-blue">TEST ONE</h3>
</div>
<div class="purchase_body_checkout_form_selectable-product">
<input type="checkbox" class="purchase_body_checkout_form_selectable-product_checkbox" />
<h3 class="purchase_body_product_name purple-blue">TEST ONE</h3>
</div>
<div class="purchase_body_checkout_form_selectable-product">
<input type="checkbox" class="purchase_body_checkout_form_selectable-product_checkbox" />
<h3 class="purchase_body_product_name purple-blue">TEST ONE</h3>
</div>
</div>
</div>
<div class="purchase_body_checkout_order-summary">
<h2 class="purchase_body_checkout_order-summary_header">Order Summary</h2>
</div>
</div>
Related
I'm trying to put 2 components side by side but I would like one of components to be on the right of the other component without the other component being reorientated.
Example:
Here, after adding a button component to the side of the "Function" heading, the "Function" heading gets pushed to the left. However, I would like the "Function" heading to be in the middle and the "TEST" at the right. As much as possible, I'd like to avoid absolute positions.
<h4 align="right" style={{display: "inline-block"}}>Function</h4><Button sx={{float: "right"}}>Test</Button>```
This is my current code but I'm unsure what I can do. Thanks in advance!
Your question is not very clear to me, but I believe you should read about flex layout CSS property.
All possible solutions of your question
.flex0 {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex1 {
display: flex;
align-items: center;
justify-content: space-around;
}
.flex2 {
display: flex;
align-items: center;
justify-content: space-evenly;
}
<div class="flex0">
<h4 align="right" style={{display: "inline-block"}}>Function</h4><Button sx={{float: "right"}}>Test</Button>
</div>
<div class="flex1">
<h4 align="right" style={{display: "inline-block"}}>Function</h4><Button sx={{float: "right"}}>Test</Button>
</div>
<div class="flex2">
<h4>Function</h4><Button>Test</Button>
</div>
There are many ways to accomplish this. But first you must understand why this misalignment happens when you use float.
Without float on button you can see it perfectly aligns to the heading with inline-block; but as soon as you introduce the float, it detaches the button as pushes it on the right side of the screen on the top corner of the block line. (image attached)
This happened because the heading tags, by default, have margins.
So to align them properly,
1st thing you can do is to provide the float button a similar margin as that of the heading.
<div>
<h4 style='display: inline-block;'>Function</h4>
<Button style='float: right; width: 50px; height: 30px; margin: 1.33em'>Test</Button>
</div>
2nd:
Wrap them in a div and use a grid with align-items: center
<div style='display: grid; grid-template-columns: 1fr 1fr; align-items: center;'>
<h4 style='display: inline-block;'>Function</h4>
<Button style='margin-left: 85%; width: 50px; height: 30px;'>Test</Button>
</div>
3rd
going the usual way, introduce left margin to the button in % (or vice-versa) i.e without float
<div>
<h4 style='display: inline-block;'>Function</h4>
<Button style='margin-left: 75%;'>Test</Button>
</div>
<div>
<h4 style='display: inline-block; margin-right: 85%;'>Function</h4>
<Button style=''>Test</Button>
</div>
Other options:
Utilise flex containers as suggested by other answers.
.flex-container {
display: flex;
}
.flex-child {
flex: 1;
border: 2px solid yellow;
}
.flex-child:first-child {
margin-right: 20px;
}
<div class="flex-container">
<div class="flex-child magenta">
Flex Column 1
</div>
<div class="flex-child green">
Flex Column 2
</div>
</div>
Hey I'm new into CSS but I dont know how to make this work. Please help me on how to make this work.
The desired outcome.
My outcome.
The problem is how to make the heading come under the location tags. like in the figma design?
Here is the HTML.
import { GrLocation } from "react-icons/gr"
<div className="container">
<img src="https://source.unsplash.com/WLxQvbMyfas" className="main-img" alt="location-img" />
<div className="tags-colum">
<GrLocation />
<p>JAPAN</p>
<p className="underline-text">View on Google Maps</p>
<div className="container-text">
<h1>Mount Fuji</h1>
</div>
</div>
</div>
Here is the CSS.
.container {
display: flex;
align-items: center;
justify-content: center;
}
.main-img {
height: 168px;
width: 125px;
border-radius: 5px;
}
.tags-colum {
display: flex;
align-items: center;
margin: 20px 20px;
}
.container-text {
display: block;
}
.underline-text {
text-decoration: underline;
}
Your problem is .tags-column is display: flex, so you cannot group all 3 of those elements together. Because the default flexbox is row-based style which means it will align all elements on the same row
For the fix,
Create a group of that left image and all content elements (.container)
Separate the location icon and JAPAN to another group with flexbox (.tags-colum)
Put Mount Fuji separately (.container-text)
Note that, .new-group is just an alias name which I'm using for demonstration, and it has no specific styles
import { GrLocation } from "react-icons/gr"
<div className="container">
<img src="https://source.unsplash.com/WLxQvbMyfas" className="main-img" alt="location-img" />
<div className="new-group">
<div className="tags-colum">
<GrLocation />
<p>JAPAN</p>
<p className="underline-text">View on Google Maps</p>
</div>
<div className="container-text">
<h1>Mount Fuji</h1>
</div>
</div>
</div>
The issue is that you have used display flex to the .tags-colum ( which is the outermost parent) to fix this you can use flex-direction: column, yes adding this will make everything stacked up, so what's the solution?
group your elements like this
<div className="container">
<img src="https://source.unsplash.com/WLxQvbMyfas" className="main-img" alt="location-img" />
<div className="tags-colum">
<div className='gp1'>
<GrLocation />
<p>JAPAN</p>
<p className="underline-text">View on Google Maps</p>
</div>
<div className="container-text">
<h1>Mount Fuji</h1>
</div>
</div>
.tags-colum {
display: flex;
align-items: flex-start;
margin: 20px 20px;
flex-direction: column;
}
.gp1 {
display: flex;
align-items: center;
}
here is an example https://codesandbox.io/s/homepage-forked-g18lgm?file=/public/index.html:56-126
or you can completely remove the display flex from the tags-colum
I'm working with formatting some divs with a flex box and thought that justify-content: space-between is the best way to do it. But, I'm running into an issue when the browser resolution changes the items become misaligned. For example if I shrink the browser size the items will wrap onto the next line which is fine since I have flex-wrap: wrap, but on the new line that is created the contents are spread between. Is it possible to remove the justify-content every time the items wrap? Sorry for the poor explanation, I'll provide a jsfiddle. Change the fiddle to 483px and the items will wrap and be placed on the next line, but instead of space between I want the items to be placed next to each other.
http://jsfiddle.net/xut5cqhw/46/
.container {
position: relative;
height: 150px;
width: 40%;
display: flex;
justify-content:space-between;
flex-wrap: wrap;
background-color: black;
}
.content {
height: 50px;
width: 50px;
margin-top: 10px;
background-color: yellow;
}
<div class = "container">
<div class="content">
</div>
<div class="content">
</div>
<div class="content">
</div>
<div class="content">
</div>
<div class="content">
</div>
</div>
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/
In my code, two inline flex divs sit next to each other.
In the first inline flex div, flex items were set to flex-direction:column-reverse. However, this affects its sibling inline flex div's position horizontally. By that I mean, the sibling flex positioned differently when the flex was set to flex-direction: column. I don't understand why this behaves like this.
My understanding is that flex-direction only controls the position of its children, i.e. flex items, and it has no effect on its sibling flex divs. But obviously this seems to be wrong. Can anyone explains why? Thanks!
.flex {
display: inline-flex;
border: solid;
margin: 10px;
}
.box {
background: papayaWhip;
width: 100px;
height: 100px;
margin: 10px;
padding: 10px;
}
.column-reverse {
flex-direction: column-reverse;
}
.column {
flex-direction: column;
}
<div class="flex column-reverse">
<div class="box">item1</div>
<div class="box">item2</div>
</div>
<div class='flex'>
<div class="box">item1</div>
<div class="box">item2</div>
</div>
<div class="flex column">
<div class="box">item1</div>
<div class="box">item2</div>
</div>
It sounds reasonable to expect that flex items in column-reverse in an inline-flex container would simply reverse, and not affect the horizontal alignment of other elements on the line.
In reality, however, this is not the case.
In an inline-flex container, column-reverse switches the direction of the flex items (as expected), but also reverses the flow of the container (upward).
From your code (three inline-flex containers, with an added red border around the parent):
This doesn't seem to be a bug. The behavior is the same cross-browser (tested in Chrome, FF, IE11).
The issue is possibly the result of two factors:
the vertical-align property
column-reverse specification rules
vertical-align
The initial value of the vertical-align property, which applies to inline-level elements, is baseline.
This is the value that is applied whether the container is column or column-reverse.
The alignment of flex item #1 doesn't change probably because (from the spec):
5.1. Flex Flow Direction: the flex-direction
property
column-reverse
Same as column, except the main-start and main-end directions are
swapped.
Note: The reverse values do not reverse box ordering: like
writing-mode and direction, they only change the direction of flow.
Painting order, speech order, and sequential navigation orders are not
affected.
If I'm reading this correctly, column-reverse doesn't actually change the order of flex items. It reverses the flow of the container. This would explain the upward expansion of the first container.
Solution #1
One method of resolving the problem, as described in #NenadVracar's answer, is to adjust the value of vertical-align. Switching from the default baseline value to top does the trick.
.flex {
display: inline-flex;
border: solid;
margin: 10px;
vertical-align: top; /* NEW */
}
.box {
background: papayaWhip;
width: 100px;
height: 100px;
margin: 10px;
padding: 10px;
}
.column-reverse {
flex-direction: column-reverse;
}
.column {
flex-direction: column;
}
<div class="flex column-reverse">
<div class="box">item1</div>
<div class="box">item2</div>
</div>
<div class='flex'>
<div class="box">item1</div>
<div class="box">item2</div>
</div>
<div class="flex column">
<div class="box">item1</div>
<div class="box">item2</div>
</div>
Solution #2
Making the parent of the inline-flex divs a flex container also solves the problem:
body {
display: flex; /* NEW */
align-items: flex-start; /* NEW; optional; to disable equal height columns */
}
.flex {
display: inline-flex;
border: solid;
margin: 10px;
}
.box {
background: papayaWhip;
width: 100px;
height: 100px;
margin: 10px;
padding: 10px;
}
.column-reverse {
flex-direction: column-reverse;
}
.column {
flex-direction: column;
}
<div class="flex column-reverse">
<div class="box">item1</div>
<div class="box">item2</div>
</div>
<div class='flex'>
<div class="box">item1</div>
<div class="box">item2</div>
</div>
<div class="flex column">
<div class="box">item1</div>
<div class="box">item2</div>
</div>
Since default vertical-align is baseline it seems that when you change order of flex items or column-reverse in this case, they are still aligned with item1 but if you change vertical-align to top they are aligned to top, vertical-align: middle will also work here Fiddle
.flex {
display: inline-flex;
vertical-align: top;
border: solid;
margin: 10px;
}
.box {
background: papayaWhip;
width: 100px;
height: 100px;
margin: 10px;
padding: 10px;
}
.column-reverse {
flex-direction: column-reverse;
}
.column {
flex-direction: column;
}
<div class="flex column-reverse">
<div class="box">item1</div>
<div class="box">item2</div>
</div>
<div class='flex'>
<div class="box">item1</div>
<div class="box">item2</div>
</div>
<div class="flex column">
<div class="box">item1</div>
<div class="box">item2</div>
</div>