Special flexbox layout - css

I'm trying to accomplish the following layout:
My first thought is to use flexbox to achieve this layout. I currently have the following HTML:
<section>
<div class"item">box1</div>
<div class"item">box2</div>
<div class"item">box3</div>
<div class"item">box4</div>
<div class"item">box5</div>
</section>
How can I achieve the desired layout with my HTML? I can add line break div elements in between items like this as well:
<div class"break"> </div>
Unfortunately I am still not able to achieve the required layout. Please help

A simple CSS-grid based approach would be to use a "template of named grid areas".
CSS grid allows for named areas, which dictate the placement of children based on the grid-area of those grid children. In the case of your requirements, a template based on named areas could be defined as:
grid-template-areas:
"a a b b c c"
". . e f . .";
These template areas work by causing:
child elements with grid-area of a, b, and c to occupy the top row of the template layout, where each spans two columns of the 6 column grid
child elements with grid-area of e and f to occupy the bottom row of the template, at the third and fourth column respectively. The . on this row configuration specifies that no child apples to that area of the template
Note that template area strings can be written on the same line for the grid-template-areas property as shown below:
section {
/* Specify that CSS grid is to be used for layout of children */
display: grid;
/* Specify spacing between children */
grid-gap:1rem;
/* Wrap against six evenly spaced columns of this grid */
grid-template-columns: repeat(6, 1fr);
/* Define the area names of the grid template */
grid-template-areas: "a a b b c c" ". . e f . .";
}
section div:nth-child(1) {
grid-area: a;
}
section div:nth-child(2) {
grid-area: b;
}
section div:nth-child(3) {
grid-area: e;
}
section div:nth-child(4) {
grid-area: f;
}
section div:nth-child(5) {
grid-area: c;
}
/* Optional aesthetics to better match your example */
div {
background: darkgrey;
border-radius: 5px;
color: white;
text-align: center;
}
<section>
<div class "item">box1</div>
<div class "item">box2</div>
<div class "item">box3</div>
<div class "item">box4</div>
<div class "item">box5</div>
</section>
Updates
section {
display: grid;
grid-gap:1rem;
grid-template-columns: repeat(5, auto);
grid-template-areas: "a b c c d e" ". . f g . .";
}
section div:nth-child(1) {
grid-area: a;
}
section div:nth-child(2) {
grid-area: b;
}
section div:nth-child(3) {
grid-area: c;
}
section div:nth-child(4) {
grid-area: f;
}
section div:nth-child(5) {
grid-area: g;
}
section div:nth-child(6) {
grid-area: d;
}
section div:nth-child(7) {
grid-area: e;
}
/* Optional aesthetics to better match your example */
div {
background: darkgrey;
border-radius: 5px;
color: white;
text-align: center;
}
<section>
<div class "item">box1</div>
<div class "item">box2</div>
<div class "item">box3</div>
<div class "item">box4 lots of content causes uneven column distribution</div>
<div class "item">box5</div>
<div class "item">box6</div>
<div class "item">box7</div>
</section>

You Can use CSS Grid Instead:
Complete Grid Guide
Working Demo:
.grid {
display: grid;
grid-template-areas: "i1 i1 i2 i2 i3 i3" ". . i4 i5 . .";
grid-template-columns: repeat(6,1fr); /* to make all boxes same with */
grid-gap: 10px;
}
.i1 {
grid-area: i1
}
.i2 {
grid-area: i2
}
.i3 {
grid-area: i3
}
.i4 {
grid-area: i4
}
.i5 {
grid-area: i5
}
.item {
min-height: 40px;
background-color: #7D7D7D;
border-radius: 10px;
display: flex;
justify-content: center;
;
align-items: center;
color: white;
font-size: 1.5rem;
font-weight: bolder;
}
.i4,.i5 {
border-radius: 8px;
}
<section class="grid">
<div class="item i1">box1</div>
<div class="item i2">box2</div>
<div class="item i3">box3</div>
<div class="item i4">box4</div>
<div class="item i5">box5</div>
</section>

With flexbox you can adjust the order of the element and rely on wrapping:
section {
display:flex;
flex-wrap:wrap;
justify-content:center;
}
section > .item {
width:calc(100%/3 - 10px);
margin:5px;
}
section > .item:nth-child(3),
section > .item:nth-child(4){
order:1;
width:calc((100%/3 - 20px) /2);
}
/* Irrelevant styles */
section > .item {
padding:10px;
box-sizing:border-box;
text-align:center;
background:#000;
color:#fff;
border-radius:10px;
}
<section>
<div class="item">box1</div>
<div class="item">box2</div>
<div class="item">box3</div>
<div class="item">box4</div>
<div class="item">box5</div>
</section>

Related

Implicit grid-area doesn't work as expected

given this html
<div class="parent">
<div class="first">1</div>
<div class="second">2</div>
<div class="third">3</div>
<div class="fourth">4</div>
</div>
and this css
.parent {
display: grid;
grid-template-areas:
'first second'
'third third'
'fourth fourth'
}
I expected the grid area "third" and "fourth" to implicitly have 1 column, which would render like so
I understand I can fix this by specifying grid-area, curious if theres another approach?
https://jsfiddle.net/qgdh2b8a/2/
This isn't a completely different approach, but you could use grid-column and not use grid-template-areas entirely. This solution also uses grid-template-columns.
.parent {
display: grid;
grid-gap: 3px;
/* Defines two columns */
grid-template-columns: 1fr 1fr;
}
.parent > div {
/* Visibility and styling */
background-color: black;
color: white;
padding: 1rem;
text-align: center;
font-family: sans-serif;
}
.third, .fourth {
/* Sets the column that the item should span */
grid-column: 1 / -1;
}
<div class="parent">
<div class="first">1</div>
<div class="second">2</div>
<div class="third">3</div>
<div class="fourth">4</div>
</div>
Here, the third and fourth classes have this style applied: grid-column: 1 / -1. The slash specifies the amount of columns that the element should span. 1 is the first column and -1 is the first from last (the last column).
Examples:
grid-column: 3 Sets the grid column to 3.
grid-column: 1 / 3 Sets the element to span columns 1 through 3.
grid-column: 1 / -2 Sets the element to span columns 1 through the 2nd last one.
You can use grid-column.
.first {
gird-column: 1 / 3; //like this
}
This tells the grid to start from the beginning of the first column, till the beginning of the third column.
The same can work for grid-rows.
You can read more here: grid-column

CSS grid different number of columns

I want to make a grid with different column sizes ('ITEM = V' covers all width 'ITEM A' or 'P' or 'T' cover each 50 percent of the grid width), as shown in the image. Any help?
i ve been tryin to solve this for a week now. Really what's wrong with this. (video should take two columns)
<div class="grid-container">
<div *ngFor="let media of allMedia">
<div *ngIf="media.type==='V'" class="item1">
{{media.title}}
</div>
<div *ngIf="media.type==='A'" >
{{media.title}}
</div>
<div *ngIf="media.type==='P'" >**Bold Text Here**
{{media.title}}
</div>
<div *ngIf="media.type==='T'">
{{media.title}}
</div>
</div>
</div>
CSS
.grid-container {
display: grid;
background-color: #2196F3;
grid-template-columns: 50% 50%;
}
.item1 {
grid-area: 2 / 1 / span 2 / span 2 !important;
border-style:solid;
text-align:center
}
It'd be best to use display: grid; for something like this.
You'd have to add unique classes/id's for the children elements and then set the grid-area property on each of them.
The layout of grid-area is:
grid-area: row-start / column-start / row-end / column end;
You can also use shorthand if two properties have the same value:
grid-area: 2 / 1
/* Equates to: */
grid-area: 2 / 1 / 2 / 1
Example:
.outer-grid {
display: grid;
height: 100vh;
}
.newspaper1 {
grid-area: 1 / 3 / 2 / 1;
border-style: solid;
}
.newspaper2 {
grid-area: 2 / 1;
border-style: solid;
}
.newspaper3 {
grid-area: 2;
border-style: solid;
}
.newspaper4 {
grid-area: 3 / 1;
border-style: solid;
}
.newspaper5 {
grid-area: 3 / 2;
border-style: solid;
}
.newspaper6 {
grid-area: 4 / 3 / 4 / 1;
border-style: solid;
}
<div class="outer-grid">
<div *ngIf="item==='V'" class="newspaper1">
some content
</div>
<div *ngIf="item==='A'" class="newspaper2">
some content
</div>
<div *ngIf="item==='P'" class="newspaper3">
some content
</div>
<div *ngIf="item==='T'" class="newspaper4">
some content
</div>
<div *ngIf="item==='A'" class="newspaper5">
some content
</div>
<div *ngIf="item==='V'" class="newspaper6">
some content
</div>
</div>
Here's a good interface for learning CSS Grid if you want to learn more: https://alialaa.github.io/css-grid-cheat-sheet/

Is it possible to make every second row in a CSS Grid to have different number of columns?

I have a container with an unknown number of children (dynamically populated). I'm using this code on the parent container:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-row-gap: 10rem;
}
Is it possible somehow to make it so that every second second row has 4 columns instead of 3, so I would end up with something like this:
A B C
A B C D
A B C
A B C D
A B C
A B C D
I've tried various methods but nothing really seemed to work.
Edit: maybe my question is not clear enough -> I have only a single container and random number of divs with the same class name which are container's direct children. The nth-child(2n) doesn't work in this case because I need every 4th element the columns to switch from 3 to 4 and vice-versa.
You cannot have different number of columns on each row because it would be against the purpose of a grid. Instead you can define a grid of 12 columns and then make your child to either take 3 columns or 4 columns:
.container {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-column-gap:2px;
grid-row-gap: 5px;
}
.container > div {
grid-column:span 3;
height:40px;
background:red;
}
.container > div:nth-child(7n + 1),
.container > div:nth-child(7n + 2),
.container > div:nth-child(7n + 3) {
grid-column:span 4;
background:blue;
}
<div class="container">
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
<div></div>
</div>
If you want to have the same size you can try the following:
.container {
display: grid;
grid-template-columns: repeat(16, 1fr);
grid-column-gap:2px;
grid-row-gap: 5px;
}
.container > div {
grid-column:span 4;
height:40px;
background:red;
}
.container > div:nth-child(7n + 1) {
grid-column:3/span 4;
}
.container > div:nth-child(7n + 3) {
grid-column:span 4/-3;
}
<div class="container">
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
<div></div>
</div>
Yes, use the .container childclass:nth-child(Xn)
Read about it here here:
A easier link: https://www.w3schools.com/cssref/sel_nth-child.asp
More information: https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child
See an example here:
https://jsfiddle.net/520Ltahd/
Use mathematics to find the correct formula for the sequence of boxes. Like this:
/*The row with 4 columns*/
.container div{
padding:20px;
display:inline-block;
width:25%;
margin:0px;
padding:0px;
background-color:blue;
}
/*The row with 3 columns*/
.container div:nth-child(7n-6),.container div:nth-child(7n-5),.container div:nth-child(7n-4) {
background: red;
width:33.333%;
margin:0px;
}

Angular 5 and CSS Grid - Cannot find grid areas - warning

I created a new Angular 5.2 project using the CLI (e.g. ng new MyApp)
Changing to the folder and running the app works fine. (e.g ng serve)
I made the following changes to the generated code (see below). There are only HTML and CSS code changes, very minor, what I posted is the entirety of the changes.
When I save the code it recompiles, and a warning is thrown:
ErrorEmittedError: (Emitted value instead of an instance of Error)
autoprefixer: D:\MyApp\src\app\app.component.css:51:7: Can not find
grid areas: header, nav, content, sidebar, ad, footer
The error seems to be related to the media query section of the CSS. If I remove that section the error goes away.
I don't remember this happening in Angular 4.x? Any ideas what's going on?
app.component.html
<div class="wrapper">
<header class="main-head">The header</header>
<nav class="main-nav">
<ul>
<li>Nav 1</li>
<li>Nav 2</li>
<li>Nav 3</li>
</ul>
</nav>
<article class="content">
<h1>Main article area</h1>
<p>In this layout, we display the areas in source order for any screen less that 500 pixels wide. We go to a two column layout, and then to a three column layout by redefining the grid, and the placement of items on the grid.</p>
</article>
<aside class="side">Sidebar</aside>
<div class="ad">Advertising</div>
<footer class="main-footer">The footer</footer>
</div>
app.compnent.css
.main-head {
grid-area: header;
}
.content {
grid-area: content;
}
.main-nav {
grid-area: nav;
}
.side {
grid-area: sidebar;
}
.ad {
grid-area: ad;
}
.main-footer {
grid-area: footer;
}
.wrapper {
display: grid;
grid-gap: 20px;
grid-template-areas:
"header"
"nav"
"content"
"sidebar"
"ad"
"footer";
}
#media (min-width: 700px) {
.wrapper {
grid-template-columns: 1fr 4fr 1fr;
grid-template-areas:
"header header header"
"nav content sidebar"
"nav content ad"
"footer footer footer"
}
nav ul {
flex-direction: column;
}
}
I am having a similar problem and the solution I have found so far isn't a great one since it duplicates code, but it may help you.
First I realize that the error is just a warning and the code complies without a problem however it is worrisome so I added the classes that I defined outside of the #media within the curly braces so with your code it would look something like this:
.main-head {
grid-area: header;
}
.content {
grid-area: content;
}
.main-nav {
grid-area: nav;
}
.side {
grid-area: sidebar;
}
.ad {
grid-area: ad;
}
.main-footer {
grid-area: footer;
}
.wrapper {
display: grid;
grid-gap: 20px;
grid-template-areas:
"header"
"nav"
"content"
"sidebar"
"ad"
"footer";
}
#media (min-width: 700px) {
.wrapper {
grid-template-columns: 1fr 4fr 1fr;
grid-template-areas:
"header header header"
"nav content sidebar"
"nav content ad"
"footer footer footer"
}
nav ul {
flex-direction: column;
}
.main-head {
grid-area: header;
}
.content {
grid-area: content;
}
.main-nav {
grid-area: nav;
}
.side {
grid-area: sidebar;
}
.ad {
grid-area: ad;
}
.main-footer {
grid-area: footer;
}
}
Again I don't like this solution but it gets rid of the error.
If you're using Sass, to not repeat yourself as much, create a partial (_grid-areas.scss) with a mixin:
#mixin grid-areas {
body {
.leftbar { grid-area: leftbar; }
.rightbar { grid-area: rightbar; }
.main { grid-area: main;
header { grid-area: header; }
#content {grid-area: content; }
}
}
}
Then import it as needed:
#import 'grid-areas';
#media screen and (max-width: 80em) {
#include grid-areas;
}
Clears my errors in CLI 1.7.2
This warning occurred while using named grid-areas in Sass.
According to the CSS Tricks article posted by iwis, the issue is due to a conflict with Autoprefixer and the IE browser's support for the grid property.
To resolve the warning from Sass I simply replaced the property grid-template-areas: with the propertygrid-template:.

CSS Grid vertical columns with infinite rows

I have a list of items of unknown length (from a CMS). I want to display them in 2 vertical columns reading down. e.g.
1 4
2 5
3 6
etc...
I am trying to achieve this with CSS grid, however, it doesn't seem possible unless you set the number of rows up front. I have tried grid-auto-flow: column as per https://gridbyexample.com/examples/example18/ but this just adds additional columns when it gets to the end.
I feel like this should be possible with grid, but I can't find a way. Anyone have any ideas?
P.S. Please don't suggest CSS text columns.
Without knowing the exact amount of items this is not possible with CSS grid alone.
The only way to get around this limitation is to add a class to your second half of the items.
body {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-flow: row dense;
/* extra styles */
grid-gap: 0.5rem;
}
span {
grid-column-start: 1;
/* extra styles */
background-color: #def;
padding: 0.5rem;
}
.second-half {
grid-column-start: 2;
/* extra styles */
background-color: #abc;
}
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span class="second-half">5</span>
<span class="second-half">6</span>
<span class="second-half">7</span>
Example:
// This is just to simulate infinite scrolling
var counter = 9;
document.addEventListener('scroll', function(e) {
if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
var span = document.createElement('span');
span.innerHTML = ++counter;
document.body.appendChild(span);
}
})
body {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 200px;
/* how much height must each element occupy! change that! */
grid-gap: 0.5rem;
}
span {
background: #3A3A3A;
text-align: center;
color: #FFFFFF;
line-height: 200px;
font-size: xx-large;
}
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<span>7</span>
<span>8</span>
One solution if your HTML is generated you can calculate the grid-template-rows property on the container element with Math.ceil( NUM_ITEMS / NUM_COLUMNS )
In React:
function VerticalColumns(props) {
// props.numColumns matches `grid-template-columns` on `.container` element
const numRows = Math.ceil(props.items.length / props.numColumns);
const style = {
gridTemplateRows: `repeat(${numRows}, 1fr)`,
};
return (
<ul className='container' style={ style }>
{ props.items.map((item, index) => (
<li key={index}>{ item }</li>
)) }
</ul>
)
}
Base CSS:
.container {
display: grid;
grid-auto-flow: column;
grid-template-columns: repeat(2, 1fr);
}
You can use a flex in which there is a container and a flex item. You can limit the height of the container and then wrap the contents of flex to continue in the next column :-
<body>
<div class="container">
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
<p>1</p>
</div>
</body>
CSS:
.container {
height: 300px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
Read more about flexbox

Resources