Need helping creating a Flex-box container that wraps and is even - html

Trying to create a 2 column, 3 row flexbox container for a food menu. The product elements (which should be 2 per row) do not wrap when shrunk. I'm looking for a way to create a wrapping layout using flexbox. Also, what would be the best way to use Media Queries for the product title to be displayed when the layout is shrunk for mobile-size?
I'm attaching my jsfiddle code:
https://jsfiddle.net/5ksd34nf/#&togetherjs=Ix1LEBTca6
(keep in mind without the images, the design changes so I'm attaching photos)
The HTML is:
`
<section class="menu-page" id="Menu">
<div class="TitleWrapper">
<h1 class="title">Menu</h1>
</div>
<div class="menu-list">
<div class="product">
<div class="imgwrapper">
<img src="images/burger.jpg" alt="Burger" class="food-image">
</div>
<div class="text">
<div class="product-content">
<h3 class="name">Burgers</h3>
<h3 class="price">10 €</h3>
</div>
<div class="ptags">
<p class="allergens">Allergens:</p>
<p class="info">Milk, Gluten</p>
</div>
</div>
</div>
How can I space out the Price from the Name using flexbox?

Basically, you can do something like this:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.flex-container {
display: flex;
flex-wrap: wrap;
}
.flex-item {
border: 1px solid gray;
width: 100%;
margin-bottom: 20px;
}
.flex-sub-item {
display: flex;
justify-content: space-between;
}
#media screen and (min-width: 400px) {
.flex-item {
width: calc((100% - 20px) / 2);
margin-right: 20px;
}
.flex-item:nth-child(2n) {
margin-right: 0;
}
}
<div class="flex-container">
<div class="flex-item">
<div class="flex-sub-item">
<div>Title</div>
<div>Price</div>
</div>
</div>
<div class="flex-item">
<div class="flex-sub-item">
<div>Title</div>
<div>Price</div>
</div>
</div>
</div>

Related

How do I correctly nest a flexbox to achieve a form layout?

I am looking to achieve the following layout:
Here is how I'm picturing it (with grids):
Black bar is the nav (we can ignore this)
A title and subtitle (purple) - these should be aligned and take up approx 70% of width - I think I've done this
A form which has 3 columns (should take up 70ish percent of the 70%, I don't want inputs to be too wide)
Column 1: Heading + text pairs
Column 2: it will have some icon/character - these must be perfectly aligned
Column 3: Heading + input boxes - these must be the same width
Here is my starting HTML:
.title-container {
display: flex;
justify-content: center;
background: red;
}
.title-item {
flex-basis: 75%;
}
.data-container {
display: flex;
justify-content: center;
background: blue;
}
.column-items {
flex-basis: 70%;
display: flex;
flex-direction: row;
}
.column-1-item {
background: green;
flex-grow: 0.5;
}
.column-2-item {
background: yellow;
flex-grow: 0.1;
align-self: center;
}
.column-3-item {
background: orange;
flex-grow: 1;
}
<div class="title-container">
<div class="title-item">
<h2>Title</h2>
<p>This is some text</p>
</div>
</div>
<div class="data-container">
<div class="column-items">
<div class="column-1-item">
<p>Heading1</p>
<p>SomeText</p>
</div>
<div class="column-2-item">
<p>--></p>
</div>
<div class="column-3-item">
<p>Heading1</p>
<input type="text" name="lname">
</div>
</div>
</div>
I have tried to expand on this, but no matter what I try, I end up further away from my design making me think there is something wrong with my initial design (and flex understanding). If I add additional 'row', it breaks my layout. I also think my data-container is wrongly setup, since this will take up far more space than I want it to
Here is a code pen.
Could someone help get me closer to my design?
I would wrap your entire html in a wrapper class so that you can get the general layout of the page like so:
<div class="wrapper">
<div class="title-container">
<h2>Title</h2>
<p>
Subtitle should be aligned with title
</p>
</div>
<div class="form-container">
<div class="item">
<div class="column">
<p>Heading1</p>
<p>Some Text</p>
</div>
<div class="column">
<p>-></p>
</div>
<div class="column">
<p>Heading1</p>
<p>[ input textfield ]</p>
</div>
</div>
<div class="item">
<div class="column">
<p>Heading3</p>
<p>Some Text</p>
</div>
<div class="column">
<p>-></p>
</div>
<div class="column">
<p>Heading2</p>
<p>[ input textfield ]</p>
</div>
</div>
<div class="item">
<div class="column">
<p>Heading3</p>
<p>Some Text</p>
</div>
<div class="column">
<p>-></p>
</div>
<div class="column">
<p>Heading3</p>
<p>[ input textfield ]</p>
</div>
</div>
<div class="item">
<div class="column"></div>
<div class="column"></div>
<div class="column submit-button">
<p>[ Button ]</p>
</div>
</div>
</div>
</div>
Then you can specify the width for the title-container and form-container with the width property. Making each of the item classes in the form container have a display: flex property lets you format the children column classes to have flex-grow: 1 so they can fill up the available space. The css then looks like:
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
outline: 1px solid red;
}
.title-container {
width: 70%;
outline: 1px solid red;
}
.form-container {
width: 50%;
outline: 1px solid red;
}
.item {
display: flex;
outline: 1px solid red;
}
.column {
/* flex-grow: 1; */
flex: 1 1 0px;
outline: 1px solid red;
}
.submit-button {
display: flex;
align-items: flex-end;
justify-content: flex-end;
}
Alternately you can remove the flex-grow: 1 property from the column class and add justify-content: space-between to the item class to get a result similar to your example.
Here is the codepen.
Your .data-container just needs a flex-direction: column; because you want the .column-items to stack.

how can I separate 2 divs equally from left and right?

Im a new in css and html. How can I separate 2 divs equally from left and right?? Here's my html code.
<div class="first-div">
<h1>About<h1>
</div>
<div class="second-div">
<h1>Services<h1>
</div>
you can try this. Learn Bootstrap grid or flexbox that would be easy for these kinds of task.
.container{
width:100%;
display:flex; /* for display it's child div beside each other */
}
.first-div,.second-div{
width:50%; /* for divide container into 2 equal divs */
border: 1px solid black; /* for border around divs */
}
<div class="container">
<div class="first-div">
<h1>About<h1>
</div>
<div class="second-div">
<h1>Services<h1>
</div>
</div>
You have several options and it all depends on your exact use case.
The first option is to set both to 50% of the available width (left and right):
.first-div {
display: inline-block;
width: 50%;
}
.second-div {
display: inline-block;
width: 50%;
}
<div class="first-div">
<h1>About</h1>
</div><div class="second-div">
<h1>Services</h1>
</div>
Another option is to use flex:
.wrapper {
display: flex;
}
.first-div {
flex-grow: 1;
}
.second-div {
flex-grow: 1;
}
<div class="wrapper">
<div class="first-div">
<h1>About</h1>
</div>
<div class="second-div">
<h1>Services</h1>
</div>
</div>
If you're not familiar with flex, flexbox froggy is a great interactive way to learn.
And a final option is to use grid:
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
}
<div class="wrapper">
<div class="first-div">
<h1>About</h1>
</div>
<div class="second-div">
<h1>Services</h1>
</div>
</div>
If you're not familiar with grid, grid garden is a great interactive way to learn.
Sidenote: make sure to also properly close the <h1> tags with a </h1>.
Try this code. Hope it useful for your question.
/* CSS */
.container-box{
width:100%;
display:flex;
}
.first-div,.second-div{
width:50%;
border:1px solid #ddd; //just to look
}
<!-- HTML -->
<div class="container-box">
<div class="first-div">
<h1>About<h1>
</div>
<div class="second-div">
<h1>Services<h1>
</div>
</div>
Check Css FlexBox .
FlexBox Tutorial
<div class="mainContainer" style="
display: flex;
justify-content: space-around;
">
<div class="first" style="
border: 1px solid;
">
<h1>About</h1><h1>
</h1></div>
<div class="second-div">
<h1>Services</h1><h1>
</h1></div>
</div>

Creating flexbox row with equal layouts *per line* [duplicate]

This question already has answers here:
Equal height children of flex items
(2 answers)
Closed 3 years ago.
I'm trying to achieve a flexbox, where the row will have the titles all lined up. Requirements:
The images won't always be the same height
The description won't always be the same height
The title could be 1 row, or 3 (depending on the length)
Here is a simple fiddle:
https://jsfiddle.net/youradds/r56j4uLe/6/
As you can see this is what you get:
This is more what I'm after:
My SCSS is:
#item-wrapper {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
.item-block {
background: yellow;
flex-grow: 0;
width: 350px;
margin: 2rem 1rem;
display: flex;
flex-direction: column;
justify-content: space-between;
align-content: center;
align-items: center;
.what-logo {
img {
max-height: 100%;
}
}
.text-info {
flex-grow: 1;
.desc {
padding: 1rem;
}
h2 {
flex-grow: 0;
}
}
.action-button {
margin: 0 auto;
}
}
}
.pure-img {
max-width: 100%;
height: auto;
display: block;
}
..and test HTML:
<div id="item-wrapper">
<div class="item-block">
<div class="what-logo">
<img src="https://bodywisegym.co.uk/2018/images/events/3/3-1562951826-3.png" class="pure-img">
</div>
<div class="text-info">
<h2>Zydrunas Savickas Seminar</h2>
<div class="desc">Bodywise Gym and Studios are proud to announce we are bringing the greatest strongman Zydrunas Savickas (Big Z) to Horsham for a seminar.</div>
</div>
Find out more »
</div>
<div class="item-block">
<div class="what-logo">
<img src="https://bodywisegym.co.uk/2018/images/events/7/7-1562936970-7.jpg" class="pure-img">
</div>
<div class="text-info">
<h2>Class for mums</h2>
<div class="desc">Join Quick HIIT</div>
</div>
Find out more »
</div>
<div class="item-block">
<div class="what-logo">
<img src="https://bodywisegym.co.uk/2018/images/events/6/6-1562936464-6.png" class="pure-img">
</div>
<div class="text-info">
<h2>Gratitude Day</h2>
<div class="desc">To spread the positivity you can bring a training partner along to workout with you or to attend one of our classes.</div>
</div>
Find out more »
</div>
<div class="item-block">
<div class="what-logo">
<img src="https://bodywisegym.co.uk/2018/images/events/4/4-1562951950-4.jpg" class="pure-img">
</div>
<div class="text-info">
<h2>The experience of non-duality</h2>
<div class="desc">Yoga & meditation workshop with Indian Spiritual Master Acharya Shree Shankar </div>
</div>
Find out more »
</div>
</div>
Important note: This is a responsive design, so I can't set a height on the image div (i.e min-height 600px) because while this kind of sorts it on wider screens:
...but then on smaller screens, it scales down to 1 element per row - and this then means we have a silly amount of padding between the image and the title on the entries with smaller images:
you could look for a visual compromise.
flex children do not align with flex children from another flex parent.
You may try centering tex-info and what-logo and add an average min-height on .desc
Demo below, play it in full page to test behavior and visual.
#item-wrapper {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
#item-wrapper .item-block {
background: yellow;
max-width: 350px;
margin: 2rem 1rem;
padding:2px;/* see me */
display: flex;
flex-direction: column;
align-items: center;
}
#item-wrapper .item-block .what-logo img {
max-height: 100%;
}
#item-wrapper .item-block .text-info,
#item-wrapper .item-block .what-logo {/* update */
margin-top: auto;
}
#item-wrapper .item-block .text-info .desc {
padding: 1rem;
min-height: 4em;/* 3 lines , average */
}
#item-wrapper .item-block .text-info h2 {text-align:center}
#item-wrapper .item-block .action-button {
margin: 0 auto;
}
.pure-img {
max-width: 100%;
height: auto;
display: block;
}
<div id="item-wrapper">
<div class="item-block">
<div class="what-logo">
<img src="https://bodywisegym.co.uk/2018/images/events/3/3-1562951826-3.png" class="pure-img">
</div>
<div class="text-info">
<h2>Zydrunas Savickas Seminar</h2>
<div class="desc">Bodywise Gym and Studios are proud to announce we are bringing the greatest strongman Zydrunas Savickas (Big Z) to Horsham for a seminar.</div>
</div>
Find out more »
</div>
<div class="item-block">
<div class="what-logo">
<img src="https://bodywisegym.co.uk/2018/images/events/7/7-1562936970-7.jpg" class="pure-img">
</div>
<div class="text-info">
<h2>Class for mums</h2>
<div class="desc">Join Quick HIIT</div>
</div>
Find out more »
</div>
<div class="item-block">
<div class="what-logo">
<img src="https://bodywisegym.co.uk/2018/images/events/6/6-1562936464-6.png" class="pure-img">
</div>
<div class="text-info">
<h2>Gratitude Day</h2>
<div class="desc">To spread the positivity you can bring a training partner along to workout with you or to attend one of our classes.</div>
</div>
Find out more »
</div>
<div class="item-block">
<div class="what-logo">
<img src="https://bodywisegym.co.uk/2018/images/events/4/4-1562951950-4.jpg" class="pure-img">
</div>
<div class="text-info">
<h2>The experience of non-duality</h2>
<div class="desc">Yoga & meditation workshop with Indian Spiritual Master Acharya Shree Shankar </div>
</div>
Find out more »
</div>
</div>
forked fiddle

Layout a flex box similar to a table?

I'm working with a framework developed in-house which depends on a certain structure to our HTML. And one of the tricky things is that each row needs its own container with its own classes and data attributes.
So here's the problem. Without drastically changing the DOM, how can I make the flex box below render essentially like an HTML table would? Or is a table the only way? The solution will have to work in both IE11 and Chrome.
I'm trying to make it look like this...
Column A | Column B | Column C
1 | 2 | 3
section {
display: flex;
flex-wrap: wrap;
}
section .col {
flex: 1 1 auto;
}
section .line-break {
flex-basis: 100%;
width: 0px;
height: 0px;
overflow: hidden;
}
<html>
<head>
</head>
<body>
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="line-break"></div>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
</body>
</html>
header, .row {
display: flex; /* aligns all child elements (flex items) in a row */
}
.col {
flex: 1; /* distributes space on the line equally among items */
}
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
If the content you are going to present is of type tabular data, then a table is the proper way.
HTML 5.1 W3C Recommendation, 1 November 2016, 4.9 Tabular data
Given that you can't, or don't want to, alter the markup, this can be done using CSS Table, and with that easily swap between any display type such as flex, block, etc., or even float, using media query etc.
I also removed the <div class="line-break"></div> element, since you don't need, though if it is rendered by a component or similar, leaving it as is won't cause any problem.
Using CSS Table
section {
display: table;
width: 100%;
}
section > * {
display: table-row;
}
section .col {
display: table-cell;
}
<html>
<head>
</head>
<body>
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
</body>
</html>
If you still need, or have to, use Flexbox, this answer of mine mention the difference between CSS Table and Flexbox on two important features:
Can flexbox handle varying sizes of columns but consistent row height?
Updated, a sample showing some useful Flexbox stuff, with varying width's and span columns.
Using Flexbox
.tbl {
display: flex;
flex-direction: column;
}
.row {
display: flex;
min-height: 50px;
}
.cell {
flex: 4;
border: 1px solid red;
}
.cell:nth-child(1) {
flex: 1;
}
.cell:nth-child(2) {
flex: 2;
}
.cell.span4-5 {
flex: 8 24px; /* col 4,5 flex-grow/border/padding */
}
.cell.span3-4 {
flex: 8 24px; /* col 3,4 flex-grow/border/padding */
}
.cell.span3-5 {
flex: 12 36px; /* col 3,4,5 flex-grow/border/padding */
}
.row:first-child .cell {
display: flex;
justify-content: center; /* center horiz. */
align-items: center; /* center vert. */
}
.row .cell {
padding: 5px;
box-sizing: border-box;
}
<div class="tbl">
<div class="row">
<div class="cell">ID </div>
<div class="cell">Nr </div>
<div class="cell">Header 1 </div>
<div class="cell span4-5"> Header 2 </div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">Content</div>
<div class="cell">Content</div>
<div class="cell">Content</div>
</div>
<div class="row">
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell span3-5">Content</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell span3-4">Content</div>
<div class="cell">Content</div>
</div>
</div>
This code works for me:
* {
box-sizing: border-box;
}
body, html {
height: 100%;
margin: 0;
}
#container {
width: 400px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
background-color: lightgrey;
padding: 10px;
}
.shelf {
flex: 1 1 auto;
width: 100%;
margin-bottom: 10px;
border: 1px solid black;
background-color: lightgreen;
display: flex;
flex-direction: row;
}
.shelf:last-child {
margin-bottom: 0;
}
.labelbox {
flex: 0 0 35%;
}
.valuebox {
flex: 0 0 65%;
}
<div id="container">
<div class="shelf">
<div class="labelbox">Name: </div> <div class="valuebox">Barry Carter</div>
</div>
<div class="shelf">
<div class="labelbox">DOB:</div><div class="valuebox">10/12/1980</div>
</div>
<div class="shelf">
<div class="labelbox">
Description:
</div>
<div class="valuebox">
This content goes on and on and will force the height to expand. And the label box to the left will
"move" with it. There need not be much of a relation other than that their parent div/flex-container is
getting taller as well.
</div>
</div>
<div class="shelf">
<div class="labelbox">Group:</div><div class="valuebox">Advanced</div>
</div>
<div class="shelf">
<div class="labelbox">End Date:</div><div class="valuebox">2020-09-20</div>
</div>
</div>
Use CSS Grid. You can style any table the way you like.
Keep in mind If your table is more than 700 rows, the fram rate will start to drop, no matter what js framework you use. react, angular, vue or vanila JS. the scrolling will get real laggy.
And the maximum you row can use is 1000. More than that the extra row will create bad graphic. But you wont reach 1000 anyway, because at 700th row, the scrolling speed, starts to get bad.
If somehow you need to display more than 1000 rows, you will visualized lib. Every js framework has a lib to do so. Basically, it will render the rows in the view port. The rows that not in the view port will not be rendered. They will only be rendered when user scrolls.
This is year 2021, chances you read this answer in the future, the browsers vendor might probably fix the performance of 1000 rows, they might even extend that limit. So try it out.

Is there a DRY way of Flex ordering?

Newbie to flex use/web development.
I currently have 6 boxes within a flex container ordered like this for mobile devices:
Mobile view
with code more or less like this (CSS not included, but the class “box” is the grey box you see above):
<div class="flex-container">
<div class=“box item” />
<div class=“text item”>
<h4>Text</h4>
</div>
<div class=“box item” />
<div class=“text item”>
<h4>Text</h4>
</div>
<div class=“box item” />
<div class=“text item”>
<h4>Text</h4>
</div>
</div>
This is what I want for mobile devices!
For desktop however, I’d like to achieve this: Desktop View
Currently, the only way I’m achieving this is by using this unappealing flex order css:
item:nth-of-type(1) {order:1;}
item:nth-of-type(2) {order:2;}
item:nth-of-type(3) {order:4;}
item:nth-of-type(4) {order:3;}
item:nth-of-type(5) {order:5;}
item:nth-of-type(6) {order:6;}
My question is, is there a way to achieve my desired goal (i.e. switching the order of items 3 and 4) without having to order every single item in the container creating a yucky, repetitive block of code?
You can accomplish that with only 2 CSS selectors, and with order defaults to 0, we re-position item 3 and 5/6, here done with a media query for screens wider than 600px, to 1 and 2.
.item:nth-of-type(3) { order:1; } /* put 3 after 4 */
.item:nth-of-type(n+5) { order:2; } /* put 5,6 after 3 */
Stack snippet
.flex-container { display: flex; flex-wrap: wrap; }
.item { height: 50px; flex-basis: 100%; }
.box { background: lightgray; }
#media (min-width: 600px) {
.item { flex-basis: 50%; }
.item:nth-of-type(3) { order:1; } /* put 3 after 4 */
.item:nth-of-type(n+5) { order:2; } /* put 5,6 after 3 */
}
<div class="flex-container">
<div class="box item"></div>
<div class="text item">
<h4>Text</h4>
</div>
<div class="box item"></div>
<div class="text item">
<h4>Text</h4>
</div>
<div class="box item"></div>
<div class="text item">
<h4>Text</h4>
</div>
</div>
As far as I know if you reorder items, you need to explicitly order items after the re-ordered items. So you could probably do:
item:nth-of-type(3) {order:4;}
item:nth-of-type(4) {order:3;}
item:nth-of-type(5) {order:5;}
item:nth-of-type(6) {order:6;}
If you only ever want to switch those two, you could wrap them in another flex container and simply switch ordering within. That way your outer flow won't have to be redefined, and you could set up the container to be reused in other areas where you need to achieve the same thing.
<div class="container">
<div class="item one">One</div>
<div class="item two">Two</div>
<div class="item three">Three</div>
<div class="switch">
<div class="item four">Four</div>
<div class="item five">Five</div>
</div>
<div class="item six">Six</div>
<div class="item seven">Seven</div>
</div>
.item {
flex: 1 0 100%;
line-height: 39px;
height: 40px;
width: 100%;
background: #cecece;
margin-bottom: 10px;
text-align: center;
}
.container {
display: flex;
flex-wrap: wrap;
}
.switch {
display: flex;
flex-wrap: wrap;
flex: 1 0 100%;
}
#media (min-width: 400px) {
.switch .item:nth-of-type(1) {
order: 2;
}
}
fiddle
In addition to TripWire's answer, you need not to set a different order number for every <div> after the 4th one.
.item:nth-of-type(3), .item:nth-of-type(4) ~ .item {order:100;}
.item:nth-of-type(4) {order:50;}
A pen: https://codepen.io/israfel/pen/eEbWWG