What I thought would be a simple layout turned out to be something I'm not able to accomplish yet.
I need the grid to be responsive and spread from one side to another (it has to be aligned with the text and box above).
I tried a few options, I commented them out for easier checking:
.big-container {
padding: 0 20%;
}
.header {
width: 100%;
height: 50px;
background-color: blue;
}
.container {
border: 1px solid black;
/* display: flex;
flex-wrap: wrap;
*/
/* display: flex;
flex-wrap: wrap;
justify-content: space-between;
*/
}
.box {
border: 1px solid black;
width: 100px;
height: 30px;
background-color: yellow;
/* float: left;
margin-left: 10px; */
}
<div class="big-container">
<div class="header"></div>
<p>Text</p>
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
I tried with flex but it doesn't sort nicely the last row, flex-wrap: wrap and float:left with some margin doesn't align correctly to the left.
If you use flexbox and set justify-content: space-between then last row will also have the same spacing instead of left align. Instead you can use grid-layout for this.
.big-container {
padding: 0 20%;
}
.header {
width: 100%;
height: 50px;
background-color: blue;
}
.container {
border: 1px solid black;
display: grid;
justify-content: space-between;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
grid-gap: 10px;
}
.box {
border: 1px solid black;
height: 30px;
background-color: yellow;
}
<div class="big-container">
<div class="header"></div>
<p>Text</p>
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
Related
im trying to achieve this layout using flex and it should be responsive without any media query
flex or grid can anyone write css for this layout?
i tried this:
.parent {
display: flex;
flex-wrap: wrap;
height: 100vh;
}
.box {
width: 33.33%;
border: 1px solid black;
min-height: 200px;
padding: 0 15px;
}
.box:first-child {
height: 100%;
min-height: 100%;
}
.box:nth-child(3n) {
min-height: 70%
}
<div class="parent">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
body {
margin:0;
}
.parent{
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 100vh;
}
.box{
flex: 0 0 33.33%;
box-shadow: 0 0 0 1px black;
padding: 0 15px;
}
.box:first-child{
flex: 1 0 100%;
}
.box:nth-child(5){
flex: 1 0 66.66%;
}
<div class="parent">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Create full width header and footer
Position sidebar next to main content area
Correct sizing of sidebar and main content area
Navigation elements positioning
I have a layout that is a sidebar and a grid both wrapped in a flexbox. I'd like to put a div underneath the grid so it can have prev/next buttons, like in this image, but I can't figure out how to do that. The grid resizes itself with the window so the grid can take as many rows as necessary and then the div should go below that, and be as wide as the grid.
This is what I have, but the div is on the right of the grid:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Boardgame Database</title>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
aside {
background-color: red;
flex: 1;
min-width: 250px;
}
.grid-container {
flex: 4;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
#flex-container {
display: flex;
flex-direction: row;
min-height: 100vh;
}
</style>
</head>
<body>
<div id="flex-container">
<aside class="sidebar">
</aside>
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>
Checkout the following Code.
#main{
display :flex;
}
#sidebar{
width:70px;
height: 300px;
border: solid black 1px;
}
#grid-area{
width:200px;
height: 300px;
border: solid black 1px;
display: block;
}
#grid{
width:200px;
height: 250px;
border: solid black 1px;
display: block;
}
<div id="main">
<div id="sidebar"></div>
<div id="grid-area">
<div id="grid"></div>
<div id="button">next / prev</div>
</div>
</div>
You should use nested flex containers. Section and bottom div should be wrapped inside another flex container with flex direction to column.
So outer flex will make sidebar & inner flex container to be side by side.
Or just use a normal div container instead of flex.
here is another example only with grid keeping the pre/next button at the bottom of the viewport:
body {
margin: 0;
}
#grid-container {
display: grid;
height: 100vh;
grid-template-columns: minmax(250px, 1fr) 4fr;
grid-template-rows: 1fr auto;
}
aside {
background-color: red;
border: 1px solid;
margin: 0.25em;
grid-row: span 2;
grid-column: 1;
}
section,
#page-buttons {
grid-column: 2;
border: solid 1px;
margin: 0.25em;
}
section {
overflow: auto;
}
#page-buttons {
display: flex;
gap: 1em;
padding: 0.5em;
background: lightgray;
justify-content: center;
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
<div id="grid-container">
<aside class="sidebar">
</aside>
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>
This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Closed 3 years ago.
I am trying to create a grid using flexbox and I cannot get the last row of items to align left as I am using justify-content: space-between. I have added a JS Fiddle below:
https://jsfiddle.net/b5f4jmhu/
The boxes in the last row space between when there aren't 4 boxes to make up a full row. Any suggestions on how to get the last row to align to the left when there aren't enough boxes to fill the row?
.boxes {
max-width: 600px;
background: #ccc;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding: 20px 20px 0 20px;
margin: 60px auto 60px auto;
}
.box {
flex: 0 0 22%;
height: 100px;
background: #222;
margin: 0 0 20px 0;
}
<div class="boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Thanks,
Jamie
With flex you cannot select the last row, but for a known amount of element on each rows, you can count them and reset the right margin on the last item if it needs to.
here it would position 2 and 3 from groups of 4.:last-chld:nth-child(xn) will help you select those two (possibilities).
example:
.boxes {
max-width: 600px;
background: #ccc;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding: 20px 20px 0 20px;
margin: 60px auto 60px auto;
}
.box {
flex: 0 0 22%;
height: 100px;
background: #222;
margin: 0 0 20px 0;
}
.box:last-of-type:nth-child(4n - 1) {
margin-right:calc(22% + 24px);/* size of one element + its margin */
}
.box:last-of-type:nth-child(4n - 2) {
margin-right:calc(44% + 48px);/* size of two elements + their margin */
}
<div class="boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
if grid is a better way to handle this, there, is a solution while using flex.
It's better to use Grids for this purpose. Check please a demo on the Codepen.
.boxes {
max-width: 600px;
background: #ccc;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 20px;
padding: 20px;
margin: 60px auto 60px auto;
}
.box {
height: 100px;
background: #222;
}
And now it will be perfectly fine =)
I've modified your fiddle, take a look:
https://jsfiddle.net/z1kLs492/
.boxes {
max-width: 600px;
background: #ccc;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding: 20px;
margin: 60px auto 60px auto;
}
.box {
width: 23%;
height: 100px;
background: #222;
margin: 1%;
}
.boxes::after {
content: "";
flex: auto;
}
hey I'm new in Flexbox and I'm trying to get it as best as I can. However i faces a problem with some heights and orders, maybe some here could help out.
Note: Don't suggest using Grid/tables please.
this is what I have right now:
this is what I want to get:
html:
<div class="movie-container">
<div class="upper-container">
<div class="image">Image</div>
<div class="title">Title</div>
<div class="more">More</div>
</div>
<div class="lower-container">
<div class="runtime">Runtime</div>
<div class="description">Description</div>
<div class="director">Director</div>
</div>
</div>
css:
.movie-container{
display:flex;
flex-flow: column wrap;
}
.upper-container {
display: flex;
width:80%;
margin:0 auto;
flex-flow: raw wrap;
}
.upper-container div {
border: 1px solid black;
padding: 10px;
}
.lower-container {
display: flex;
width:80%;
margin:0 auto;
flex-flow: column wrap;
}
.lower-container div {
border: 1px solid black;
padding: 10px;
}
.image {
flex: 1;
}
.title {
flex: 3;
}
.more {
flex: 0.1;
}
.runtime{
}
.description{
}
.director{
}
Maybe other stuff need to be added beside flexbox I'm not sure, that's why I ask here. Any solution will be helpful!
If you change your HTML structure slightly you can accomplish this fairly easily:
<div class="movie-container">
<div class="upper-container">
<div class="image">Image</div>
<div class="side-container">
<div class="title">Title</div>
<div class="more">More</div>
<div class="runtime">Runtime</div>
<div class="description">Description</div>
</div>
</div>
<div class="lower-container">
<div class="director">Director</div>
</div>
</div>
JSFiddle
Flex isn't very good at stretching across multiple rows / columns like tables or Grid is, while you state you don't want that solution it is typically a better option in cases like this.
I find it easiest to work with flexbox on a row-by-row basis instead of using wrapping (although you can certainly do that too).
As a starting point, I think this snippet is what you're going for?
div {
flex: 1 1 auto;
}
.box {
border: 1px solid black;
}
.flex {
display: flex;
}
.image {
width: 120px;
flex: 0 0 auto;
}
.more {
flex: 0 0 auto;
}
<div class="flex upper">
<div class="box flex image">Image</div>
<div class="upper-detail">
<div class="flex title-container">
<div class="box title">Title</div>
<div class="box more">More</div>
</div>
<div class="box runetime">Runtime</div>
<div class="box director">Director</div>
</div>
</div>
<div class="box description">Description</div>
<div class="box other">Other stuff...</div>
Hope this helps.
.upper-container{
display: flex;
height: 200px;
}
.upper-left{
background: #ddd;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.upper-right{
flex: 3;
display: flex;
flex-direction: column;
height: 100%;
}
.title-more, .runtime, .director{
flex: 1;
border: 1px solid #222;
display: flex;
align-items: center;
}
.lower-container{
border: 1px solid #222;
padding: 10px;
}
.title-more{
justify-content: space-between;
}
.more-button{
height: 30px;
width: 100px;
border: 1px solid #333;
margin-right: 5px;
display: flex;
align-items: center;
justify-content: center;
}
<div class="movie-container">
<div class="upper-container">
<div class="upper-left">
Image
</div>
<div class="upper-right">
<div class="title-more">
<div class="title-container">
Title
</div>
<div class="more-button">
More
</div>
</div>
<div class="runtime">Runtime</div>
<div class="director">Director</div>
</div>
</div>
<div class="lower-container">
Description
</div>
</div>
The key is to add some divs and remove some others:
.movie-container *{padding:.5em;}
.upper-container {
display: flex;
padding:0;
}
.image {
border: 1px solid;
flex: 1 1 25%;
}
.tmrd{flex: 1 1 75%;padding:0}
.title-more {
display: flex;
padding:0;
}
.title{flex: 1 1 75%;border: 1px solid;}
.more{flex: 1 1 25%;border: 1px solid;}
.runtime,.description,.director{border: 1px solid;}
<div class="movie-container">
<div class="upper-container">
<div class="image">Image</div>
<div class="tmrd">
<div class="title-more">
<div class="title">Title</div>
<div class="more">More</div>
</div>
<div class="runtime">Runtime</div>
<div class="description">Description</div>
</div>
</div>
<div class="director">Director</div>
</div>
I'm trying to get an element to have items aligned to the right, and all overflowing elements to be hidden but accessed by scrollbar.
But it seems like the scrollbar disappears when specifying justify-content: flex-end. Why is that, and how do I fix it?
Here is demo: https://jsfiddle.net/efguz4mp/1/
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
justify-content: flex-end;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
...and here is demo without justify-content: flex-end;: https://jsfiddle.net/efguz4mp
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
When an overflow occur to the left (or top), a scroll doesn't get rendered, and the reason is that a HTML document's normal flow is left-to-right (top-to-bottom).
Flexbox has a row-reverse direction, which will solve that, thought 2 things comes with that:
One need to reorder the items or use an inner wrapper
I.a. Firefox and Edge doesn't show the scroll (possible bug)
Stack snippet
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
flex-direction: row-reverse;
overflow: auto;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
/* no wrapper */
.row > .box:nth-child(1) { order: 6; }
.row > .box:nth-child(2) { order: 5; }
.row > .box:nth-child(3) { order: 4; }
.row > .box:nth-child(4) { order: 3; }
.row > .box:nth-child(5) { order: 2; }
.row > .box:nth-child(6) { order: 1; }
/* wrapper */
.inner {
display: flex;
}
<div class="row">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
<div><br><br></div>
<div class="row">
<div class="inner">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
</div>
Possible workarounds are:
Use direction: rtl to change the flow direction
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
direction: rtl;
}
.inner {
display: flex;
direction: ltr;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="inner">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
</div>
Use transform to flip the row element
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
transform: scale(-1,1); /* flip horizontally */
}
.inner {
display: flex;
transform: scale(-1,1); /* reset so items is not backwards */
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="inner">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
</div>
Use a script on page load to scroll to the right
window.addEventListener("load", function(e) {
var el = document.querySelector(".row");
el.scrollLeft = el.scrollWidth;
});
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
The main problem is that you're dealing with a contradiction:
The justify-content property is designed to distribute extra space in the container.
However, an overflow condition occurs when there is no space left in the container.
Basically, justify-content and overflow have no association. The former applies only inside the container. The latter applies only outside the container.
With justify-content: flex-end, the flex items must be packed at the end of the container (not the end of the flex-start overflow area).
If the end-aligned items are too big to fit in the container, they will overflow on the start side, which is what you're seeing in your layout. But because the overflow property only applies in the direction of the writing mode (LTR, in this case), scrollbars are not rendered (more details).
So I would suggest forgetting about justify-content to make this layout work.
Instead, consider this: Use an invisible spacer item to push your content items to the right.
.row {
display: flex;
overflow: auto;
max-width: 500px;
background: #DADADA;
}
.box {
flex: 0 0 200px;
height: 40px;
margin: 4px 10px;
background: red;
}
.row::before {
content: "";
flex: 0 0 400px;
visibility: hidden;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
You'll notice that the last item margin collapses. That issue is explained here:
Last margin / padding collapsing in flexbox
Here's how I would recommend you do it
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
flex: 1;
display: flex;
overflow: auto;
}
.box {
display: flex;
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>