css-grid: place element "outside" of grid - css

I am new to css grid I try to achieve the layout from the image attached where ONE element DIV 4 is wider than the grid layout. I try to avoid to close the grid-div before DIV 4 and then reopen the grid after DIV 4 again so I can controll the appearance of each grid element and how it is displayed through ONE css-class only and it won't need a different div-structure.
https://codepen.io/anon/pen/RBdjbd
.grid-2er {
grid: auto-flow dense / 1fr 1fr;
display: grid;
grid-gap: 20px;
grid-auto-rows: auto;
}
.grid-2er .halfwidth {
grid-column: 1 / -1;
}
.grid-2er .fullwidth {
grid-column: 1 / -1;
}

Might I suggest a four column grid
grid-template-columns: 1fr minmax(0, 400px) minmax(0, 400px) 1fr;
Codepen Demo
* {
margin: 0;
padding: 0;
text-decoration: none;
outline: none;
font-weight: 300;
border: none;
font-family: "Source Sans Pro", sans-serif;
text-align: center;
}
*,
*::after,
*::before {
box-sizing: border-box;
}
.grid-2er {
grid-template-columns: 1fr minmax(0, 400px) minmax(0, 400px) 1fr;
display: grid;
grid-gap: 20px;
grid-auto-rows: auto;
}
.grid-2er * {
background: blue;
color: white
}
.grid-2er .mainwidth {
grid-column: 2 / 4;
}
.grid-2er .halfwidth {
grid-column: 2;
}
.halfwidth+.halfwidth {
grid-column: 3;
}
.grid-2er .fullwidth {
grid-column: 1 / -1;
}
<div class="grid-2er">
<div class="mainwidth">DIV 1</div>
<div class="halfwidth">DIV 2</div>
<div class="halfwidth">DIV 3</div>
<div class="fullwidth">DIV 4</div>
<div class="halfwidth">DIV 5</div>
<div class="halfwidth">DIV 6</div>
</div>

You can use negative margin. If the width of the whole grid is maximized to 800px then you can have a negative margin of (800px - 100vw)/2 on each side. Then when the size of the window is less than 800px you reset margin to 0:
Here is an example (I used 600px in this case)
* {
margin: 0;
padding: 0;
font-weight: 300;
border: none;
font-family: "Source Sans Pro", sans-serif;
text-align: center;
padding: 10px;
}
*,
*::after,
*::before {
box-sizing: border-box;
}
.grid-2er {
grid: auto-flow dense / 1fr 1fr;
display: grid;
grid-gap: 20px;
grid-auto-rows: auto;
max-width: 600px;
margin: auto;
}
.grid-2er .halfwidth {
grid-column: 1 / -1;
background: blue;
color: white
}
.grid-2er .fullwidth {
grid-column: 1 / -1;
background: blue;
color: white
}
.outside {
margin: 0 calc((600px - 100vw)/2);
}
#media only screen and (max-width: 600px) {
.outside {
margin: 0;
}
}
#media only screen and (min-width: 480px) {
.grid-2er .halfwidth {
grid-column: auto;
}
.grid-2er .fullwidth .tile {
width: 50%;
}
}
<div class="grid-2er">
<div class="fullwidth ">
DIV 1
</div>
<div class="halfwidth">
DIV 2
</div>
<div class="halfwidth">
DIV 3
</div>
<div class="fullwidth outside">
DIV 4
</div>
<div class="halfwidth">
DIV 5
</div>
<div class="halfwidth">
DIV 6
</div>
</div>

Use calc to get the value of your gutter. The width of the gutter is half the width of it's container minus half the width of the content container. In your case the math is calc(50% - 400px). I like to add a minmax to keep the gutter from collapsing completely but you can ignore that if you don't need it. This frees you up to use 1fr for your interior columns so they are responsive and you can change the number of columns without having to recalculate their widths.
.content {
display: grid;
grid-template-columns: calc(50% - 400px) repeat(2, 1fr) calc(50% - 400px);
gap: 1rem;
}
.column {
text-align: center;
background-color: #ddd;
}
.--column1 {
grid-column: 2 / 3;
}
.--column2 {
grid-column: 3 / 4;
}
.--columnfull {
grid-column: 1 / 5;
}
<div class="container">
<div class="content">
<div class="column --column1">column</div>
<div class="column --column2">column</div>
<div class="column --columnfull">column</div>
</div>
</div>

Related

How to make my grid cell same size after spanding it over the next cell?

enter image description here
How do I make my grid cell same size after spanning it over the next cell? This is what I have tried so far
.factory {
display: grid;
grid-template-columns: 1fr 1fr 2fr;
height: 600px;
gap: 10px;
margin-top: 100px;
padding: 10px;
}
.factory>div {
background-color: gray;
border: 1px green solid;
}
.image-1 {
width: 100%;
height: auto;
}
.div-3 {
grid-column: 3 / span 5;
}
.div-5 {
grid-column: 1 / span 2;
}
<div class="factory">
<div class="div-1">box1</div>
<div class="div-2">box2</div>
<div class="div-3">box3</div>
<div class="div-5">box5</div>
<div class="div-6">box6</div>
</div>
As you can see box6 is smaller than the rest of the boxes.
Your issue is that on div-3 you try to span 5 columns after it has started at column 3 which will make the browser attempt to add 5 more columns to the grid.
.div-3 {
grid-column: 3 / span 5;
}
You can either remove this section completely because you have already specified in your grid-template-columns: 1fr 1fr 2fr; that the third column should be double the space of the first two.
Another option would be to span 1
.div-3 {
grid-column: 3 / span 1;
}
You can see this clearly by using the inspection tools.
.factory {
display: grid;
grid-template-columns: 1fr 1fr 2fr;
height: 600px;
gap: 10px;
margin-top: 100px;
padding: 10px;
}
.factory>div {
background-color: gray;
border: 1px green solid;
}
.image-1 {
width: 100%;
height: auto;
}
/*.div-3 {
grid-column: 3 / span 5;
}*/
.div-5 {
grid-column: 1 / span 2;
}
<div class="factory">
<div class="div-1">box1</div>
<div class="div-2">box2</div>
<div class="div-3">box3</div>
<div class="div-5">box5</div>
<div class="div-6">box6</div>
</div>

How to overlap elements in css using grid

I want to place box 2 on top of both other boxes by half of them, however, even having explicitly defined grid-template-columns propriety to 1fr it automatically creates another column.
Here is my attempt
index.html
<div class="grid-overlap">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
style.scss
.grid-overlap {
max-width: 40rem;
width: 95%;`your text`
margin: 2rem auto;
gap: 1rem;
display: grid;
grid-template-rows: repeat(4, 1fr);
grid-template-columns: 1fr;
.box {
width: 300px;
height: 300px;
margin: 0 auto;
text-align: center;
font-size: 3rem;
}
.box:nth-child(1) {
grid-row: 1 / 3;
background-color: dodgerblue;
}
.box:nth-child(2) {
background-color: red;
grid-row: 2 / 4;
z-index: 100;
}
.box:nth-child(3) {
grid-row: 3 / 5;
background-color: tomato;
}
}
Thanks in advance.
I am giving one example of overlap, try to see how it works and use it in your use case.
.grid-overlap {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
}
.grid-overlap .box:nth-child(1) {
grid-row: 1/3;
grid-column: 1/3;
background-color: dodgerblue;
}
.grid-overlap .box:nth-child(2) {
background-color: rgba(255, 0, 0, 0.6);
grid-row: 2/4;
grid-column: 2/4;
}
<div class="grid-overlap">
<div class="box">1</div>
<div class="box">2</div>
</div>
Looking at the grid we can see that the second square starts in the middle of the first one and that the last one is positioned at one quarter along and three quarters down the first square.
This leads to a grid of width 6 and height 7 square cells.
As it's not possible to have both the grid imensions set at 300px and the width of the grid to be defined in rems (and % units) this snippet drops the 300px settings and sets the overall grid to be the width as defined in the question and the aspect ratio 6/7.
Note that the grid gap is not set (defaults to 0) as no gap was shown in the picture given in the question.
body {
width: 100vw;
height: 100vh;
}
.grid-overlap {
max-width: 40rem;
width: 95%;
aspect-ratio: 6 / 7;
margin: 2rem auto;
gap: 1rem;
gap: 0;
display: grid;
grid-template-rows: repeat(7, 1fr);
grid-template-columns: repeat(6, 1fr);
}
.box {
/*width: 300px;
height: 300px;*/
width: 100%;
height: 100%;
margin: 0 auto;
text-align: center;
font-size: 3rem;
}
.box:nth-child(1) {
grid-column: 1 / span 4;
grid-row: 1 / span 4;
background-color: dodgerblue;
}
.box:nth-child(2) {
background-color: red;
grid-column: 3 / span 4;
grid-row: 3 / span 4;
z-index: 100;
}
.box:nth-child(3) {
grid-column: 2/ span 4;
grid-row: 4 / span 4;
background-color: tomato;
}
<body>
<div class="grid-overlap">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
</body>
If the important dimensions were the 300px then use those to set the width of the overall grid.

Using CSS Grid and getting specifically content to fit

I am trying to use grid-template-columns: auto auto min-content auto; But I am not getting it to work properly.
I would like the content in the yellow block to fit exactly the content present. This content will be variable and may change. However when i run the following code. It breaks the content into the second line when I just want it to fill everything in the first line. So in this case October will be in the first line and 25 comes below. I would like it to be on the same line, bearing in mind that this content will be variable.
.box {
color: #FFF;
font-family: sans-serif;
}
.box--green {
background-color: #3D9970;
}
.box--blue {
background-color: #0074D9;
}
.box--yellow {
background-color: #FFDC00;
}
.box--red {
background-color: #FF4136;
}
/*
* position your boxes wherever you want in your grid
*/
.swimmeet-meta {
display: grid;
grid-template-columns: 30px 30px fit-content auto;
grid-template-rows: repeat(2, 1fr);
/* 2 rows */
}
.swimmeet-meta__item--play {
grid-area: 1 / 1 / 3 / 3;
}
.swimmeet-meta__item--title {
grid-area: 1 / 3 / 2 / 5;
grid-column-start: 3;
grid-column-end: 5;
}
.swimmeet-meta__item--date {
grid-area: 2 / 3 / 3 / 4;
}
.swimmeet-meta__item--time {
grid-area: 2 / 4 / 3 / 5;
}
<main class="swimmeet-meta">
<div class="box swimmeet-meta__item--play box--green">Book</div>
<div class="box swimmeet-meta__item--title box--blue">Join swim meeting soon daily</div>
<div class="box swimmeet--meta__item--date box--yellow">October 26</div>
<div class="box swimmeet--meta__item--time box--red">1 hour</div>
</main>
adjust your template to be grid-template-columns: 30px 30px auto 1fr; and simplify your code like below:
.box {
color: #FFF;
font-family: sans-serif;
}
.box--green {
background-color: #3D9970;
}
.box--blue {
background-color: #0074D9;
}
.box--yellow {
background-color: #FFDC00;
}
.box--red {
background-color: #FF4136;
}
.swimmeet-meta {
display: grid;
grid-template-columns: 30px 30px auto 1fr;
grid-template-rows: repeat(2, 1fr);
}
.swimmeet-meta__item--play {
grid-area: span 2/span 2;
}
.swimmeet-meta__item--title {
grid-column: span 2;
}
<main class="swimmeet-meta">
<div class="box swimmeet-meta__item--play box--green">Book</div>
<div class="box swimmeet-meta__item--title box--blue">Join swim meeting soon daily</div>
<div class="box swimmeet--meta__item--date box--yellow">October 26</div>
<div class="box swimmeet--meta__item--time box--red">1 hour</div>
</main>

Css-grid: Bleed background outside container

Consider the following 3-column grid layout with max-width constraint on container:
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 56px minmax(56px, auto) 56px;
max-width: 300px;
margin: auto;
}
header {
background-color: grey;
grid-column: 1 / span 3;
grid-row: 1 / 2;
}
main {
background-color: #2E64FE;
grid-column: 1 / span 2;
grid-row: 2 / 3;
}
aside {
background-color: #FF0040;
grid-column: 3 / span 1;
grid-row: 2 / 3;
}
footer {
background-color: grey;
grid-column: 1 / span 3;
grid-row: 3 / 4;
}
header, main, aside, footer {
line-height: 56px;
text-align: center;
vertical-align: middle;
}
<html>
<body>
<div class='container'>
<header>Header</header>
<main>Main</main>
<aside>Sidebar</aside>
<footer>Footer </footer>
</div>
</body>
</html>
Ideally, I would like to bleed background of header and footer outside the container when viewport width is above max-width, but keep grid and its structure within max-width as in example (including inner content of header and footer).
I have considered these approaches:
Forget max-width container, use full width container with minmax'es and position full-span divs with background-color underneath header and footer(https://codepen.io/anon/pen/OaryXj). I don't like this approach because it adds extra elements purely for styling and because it adds two extra columns (I can live with this one probably, using named columns)
Use same approach as above, but instead of adding extra divs, use full-span header and footer with "padding: 0 calc((100% - 900px)/2);" (https://codepen.io/anon/pen/BGvoxx). I don't like this approach either, because I don't understand why it works at all when 100% < 900px (why negative padding is not added) and it adds two extra columns to the grid as well.
Any other ideas? Some calc() magic with negative margins and padding on header / footer?
if it's only about background and coloration you can use pseudo element to have the overflow effect:
body {
overflow-x:hidden;
}
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 56px minmax(56px, auto) 56px;
max-width: 300px;
margin: auto;
}
header {
background-color: grey;
grid-column: 1 / span 3;
grid-row: 1 / 2;
position:relative;
}
header:before,
footer:before{
content:"";
z-index:-1;
position:absolute;
top:0;
bottom:0;
left:-100vw;
right:-100vw;
background:inherit;
}
main {
background-color: #2E64FE;
grid-column: 1 / span 2;
grid-row: 2 / 3;
}
aside {
background-color: #FF0040;
grid-column: 3 / span 1;
grid-row: 2 / 3;
}
footer {
background-color: grey;
grid-column: 1 / span 3;
grid-row: 3 / 4;
position:relative;
}
header, main, aside, footer {
line-height: 56px;
text-align: center;
vertical-align: middle;
}
<html>
<body>
<div class='container'>
<header>Header</header>
<main>Main</main>
<aside>Sidebar</aside>
<footer>Footer </footer>
</div>
</body>
</html>
the accepted answer is amazing, but you can solve your problem by changing your markup a little bit. by changing the order of your divs and splitting the concerns of your container class with that of the grid you get the same result:
body {
margin: 0;
overflow-x:hidden;
}
.container {
max-width: 300px;
margin: auto;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: minmax(56px, auto);
}
header, footer {
background-color: grey;
height: 56px;
}
main {
background-color: #2E64FE;
grid-column: 1 / span 2;
}
aside {
background-color: #FF0040;
grid-column: 3 / span 1;
}
header, main, aside, footer {
line-height: 56px;
text-align: center;
vertical-align: middle;
}
<html>
<body>
<header>
<div class="container">Header</div>
</header>
<div class="container grid">
<main>Main</main>
<aside>Sidebar</aside>
</div>
<footer>
<div class="container">Footer</div>
</footer>
</body>
</html>
the use-case where I see the accepted answer really shine is when you have multiple columns and you don't want to break the grid but extend the background color of one of the columns to the edges of the browser...
body {
overflow-x:hidden;
margin: 0;
}
.container {
max-width: 300px;
margin: auto;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: minmax(56px, auto);
}
header, footer {
background-color: grey;
height: 56px;
}
aside {
background-color: #FF0040;
grid-column: 1 / span 1;
}
main {
background-color: #2E64FE;
grid-column: 2 / span 2;
}
.extend-right {
position: relative;
}
.extend-right:after {
content: '';
position: absolute;
height: 100%;
left: 100%;
right: -100vw;
background-color: inherit;
}
header, main, aside, footer {
line-height: 56px;
text-align: center;
vertical-align: middle;
}
<html>
<body>
<header>
<div class="container">Header</div>
</header>
<div class="container grid">
<aside>Sidebar</aside>
<main class="extend-right">Main</main>
</div>
<footer>
<div class="container">Footer</div>
</footer>
</body>
</html>

Is it possible to split a grid item to allow different spans?

I have an article and an aside (sidebar) element - easy, except the title and sub-heading of the article need to span the entire row. If I take the title/sub-heading out of the article, the article element is no longer semantically complete.
Is there a way, using CSS Grid, to have the format below, where Title, Sub and Content are all a part of an "Article" element, and "Aside" is the second in a 2 column grid?
From my research so far, it seems this is not possible.
You can hack your way through using nested CSS grid if you know:
The width of the aside section
The height of the title and sub heading sections
(in many layouts, these dimensions are fixed)
You can use a pseudo element that create a space for the aside element and then sneak it inside the outer grid container - check out the demo below:
body {
margin: 0;
}
* {
box-sizing: border-box;
}
article,
aside {
border: 1px solid;
display: flex;
align-items: center;
justify-content: center;
}
div {
display: grid;
grid-template-areas: "section aside";
}
section {
grid-area: section;
display: grid;
grid-template-areas: "header header" "subhead subhead" "content empty";
grid-template-rows: 50px 50px auto;
grid-template-columns: 80vw auto;
height: 100vh;
width: 100vw;
}
section article:first-child {
grid-area: header;
}
section article:nth-child(2) {
grid-area: subhead;
}
section article:last-child {
grid-area: content;
}
section:after {
content: '';
display: block;
grid-area: empty;
}
aside {
grid-area: aside;
height: calc(100vh - 100px);
width: 20vw;
align-self: flex-end;
position:relative;
transform: translateX(-100%);
}
<div>
<section>
<article>Article title</article>
<article>Article sub-heading</article>
<article>Article content</article>
</section>
<aside>Aside</aside>
</div>
You can use something like this.
* {box-sizing: border-box;}
.wrapper {
max-width: 940px;
margin: 0 auto;
}
.wrapper > div {
border: 2px solid rgb(233,171,88);
border-radius: 5px;
background-color: rgba(233,171,88,.5);
padding: 10px;
color: #d9480f;
}.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
grid-auto-rows: minmax(100px, auto);
}
.one {
grid-column: 1 / 4;
grid-row: 1;
}
.two {
grid-column: 1 / 4;
grid-row: 2;
}
.three {
grid-column: 1 / 3;
grid-row: 3;
min-height:200px;
}
.four {
grid-column: 3;
grid-row: 3;
min-height:200px;
}
<div class="wrapper">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
<div class="four">Four</div>
</div>
Also check Fiddle.
And for more details please visit https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout
You can achieve that by simply floating all the cells, as long as the article doesn't float - https://jsfiddle.net/yxbckzcq/1/
<div class="wrapper">
<article>
<div style="float:left;width:100%" class="one">One</div>
<div style="float:left;width:100%" class="two">Two</div>
<div style="float:left;width:70%" class="three">Three</div>
</article>
<div style="float:left;width:30%" class="four">Four</div>
</div>

Resources