Overlapping grid items using grid-template-areas / named areas - css

I'm experimenting with CSS Grids, and this is the layout I'm building:
.grid {
display: grid;
align-items: center;
grid-template-columns: 1fr 4rem 1fr;
grid-template-rows: 1rem 1fr 1rem;
max-width: 900px;
margin: 0 auto;
}
.text {
/*
// Ideally, this should be
grid-area: text
*/
grid-column: 1 / 3;
grid-row: 2 / 3;
/* Fix z-index */
position: relative;
padding: 4rem;
background-color: #fff;
}
.image {
/*
// Ideally, this should be
grid-area: image;
*/
grid-column: 2 / 4;
grid-row: 1 / -1;
background-color: lightgray;
padding: 1rem;
/* Center das image */
display: flex;
justify-content: center;
}
/* Basic body */
body {
background-color: #fafafa;
font-family: sans-serif;
padding: 2rem;
}
img {
max-width: 100%;
height: auto;
}
<div class="grid">
<div class="text">One morning, when bobby woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his leg like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into
stiff sections.
</div>
<div class="image">
<img src="http://unsplash.it/400/400" />
</div>
</div>
(best to preview in full page...)
What I'd like to avoid:
.text and .image both currently are using grid-column: * / *; syntax, instead I'd like to use grid-area: text and grid-area: image;.
Is it possible to define grid-template-{columns|rows} as overlapping areas? I tried using second way of defining grid areas
, but that didn't seem to work.
Looks like you can't do [a-start] [b-start] [a-end] [b-end] in that syntax, or at least I didn't manage to.
So - Is there any way to create an overlapping grid using named areas?
I'm trying to use the named areas for convenience purely - so that it's easier to reason about the responsive layout code, instead of repeating myself multiple times in media queries.
Edit
Found the answer because of #vals answer below.
This seemed to work just fine, I probably made a syntax error in my previous attempt somewhere:
grid-template-columns: [text-start] 1fr [image-start] 4rem [text-end] 1fr [image-end];
grid-template-rows: [image-start] 1rem [text-start] 1fr [text-end] 1rem [image-end];

At least in a more basic layout, it seems to work for me:
.container {
border: solid 1px green;
height: 180px;
width: 300px;
display: grid;
grid-template-columns: [left-start] 100px [right-start] 100px [left-end] 100px [right-end];
grid-template-rows: [left-start] 60px [right-start] 60px [left-end] 60px [right-end];
}
.left {
grid-area: left;
background-color: red;
}
.right {
grid-area: right;
background-color: lightgray;
opacity: 0.5;
}
<div class="container">
<div class="left">
</div>
<div class="right">
</div>
</div>

Related

CSS Grid 2 columns and 1 row, H1 creates new row

I am using CSS grid for a website, and in the information section I have 2 columns:
on the left a paragraph with information, on the right the image.
However, when I want to add an h1 to the paragraph it creates an extra column, resulting in:
On the left the header, on the right the image and underneath the header is now the paragraph.
I've now avoided the problem by using and making a class for the first sentence of the paragraph (making that sentence look like a h1) but it feels like a makeshift solution. Is there a better way to solve this problem?
I've tried 2fr 2fr, still the same problem
I've added a screenshot of what it looks like
(I'm still very new to CSS grid)
.block1{
display:grid;
grid-template-columns: 1fr 2fr;
column-gap: 250px;
background-color: #EFEDE3;
padding: 150px;
}
.block1 img{
justify-self: end;
border-radius: 5px;
width: 75%;
}
.block1 span {
font-weight: bolder;
font-size: 32px;
}
You can try this one.
HTML:
<div class="grid">
<div class="paragraph">
<h1>Paragraph</h1>
</div>
<div class="imageBox">
</div>
</div>
and CSS:
.grid {
display: grid;
grid-template-columns: 1fr 2fr;
column-gap: 250px;
}
.paragraph {
border: 1px solid green;
height: 40vh;
}
.imageBox {
border: 1px solid red;
height: 40vh;
}

Can a responsive page layout be achieved using css grid and flexbox without media queries?

I'm trying to achieve this layout (https://codepen.io/totkeks/pen/PowodPq) with a top section, main section and side section.
<div class="grid">
<div class="top">Top</div>
<div class="main">Main</div>
<div class="side">Side</div>
</div>
body {
padding: 0;
margin: 0;
}
.grid {
display: grid;
grid-gap: 3rem;
grid-template-columns: 22rem minmax(48rem, auto);
grid-auto-rows: auto;
padding: 3rem;
min-height: 100vh;
box-sizing: border-box;
border: 2px dotted black;
}
.top, .main, .side {
background-color: papayawhip;
}
.main {
grid-row: span 2;
}
#media screen and (max-width: 1200px) {
.grid {
grid-template-columns: 1fr;
}
}
When the page is smaller (< 1280px currently in CSS query) the three sections are stacked on top of each other, first top, then main, then side, all covering the full width.
When the page is wider, the top and side sections are fixed size on the left side and the main section is on the right side, growing as space becomes available.
Just a moment ago I found this Q&A Responsive layout without media query and while it goes in the right direction, it is not entirely what I'm trying to achieve.
I already spent two evenings with this idea and would like to find a solution or get a definitive "No, that's not possible with current CSS".
You could give a try with auto-fit, grid-colum, grid-row and use width + calc() to trick the wrapping . But you could find funny behaviors from a browser to anoter . (auto-flow is required ) However, mediaquerie is made for this, much cleaner and reliable.
body {
padding: 0;
margin: 0;
}
.grid {
display: grid;
grid-gap: 3rem;
margin: 1em;
border: solid;
grid-template-columns: repeat(auto-fit, minmax(22rem,auto));
grid-auto-rows: auto;
padding: 3rem;
min-height: calc(100vh - 2em);
box-sizing: border-box;
}
.top,
.main,
.side {
background-color: orange;
border:solid;
}
.top,
.side {
grid-column: 1;
width: 22rem;
min-width:100%;
}
.main {
grid-column: auto;
min-width: calc(100vw - 33rem);
grid-row: span 2;
}
<div class="grid">
<div class="top">Top</div>
<div class="main">Main</div>
<div class="side">Side</div>
</div>
My answer maybe yes for the fun only.

How to overlap image tag as a background over two CSS Grid areas

The image is an img tag and needs to be stretched as a background image over two areas 'img' and 'content'. The text has to go above the stretched image in the 'content' area. Simple but how? I can't find any obvious answers online.
.media {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
width: 100%
}
.media {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas: "img content";
margin-bottom: 1em;
}
.image {
grid-area: img;
background-color: #ffd8a8;
}
.text {
grid-area: content;
padding: 10px;
}
<div class="media">
<img class="image" src="https://loremflickr.com/500/200" />
<div class="text">This is a media object example.
  We can use grid-template-areas to switch around the image and text part of the media object.
  </div>
</div>
Modify your code as follows:
.media {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
width: 100%
}
.media {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas: "img content";
margin-bottom: 1em;
}
.image {
grid-area: img;
background-color: #ffd8a8;
}
.text {
grid-area: content;
padding: 10px;
}
.media {
background-image: url("https://loremflickr.com/700/200");
background-repeat: no-repeat;
height: 150px;
}
<div class="media">
<div class="text">This is a media object example. We can use grid-template-areas to switch around the image and text part of the media object.
</div>
</div>
Here is a screenshot of the output:
There are many ways to get the desired result.
You could also make the image a background of the DIV rather than having an IMG tag inside the DIV.
But I sticked to your code below and just added CSS to place the text DIV on top of the image and stretch the image to 100% with hidden overflow.
.media {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
width: 100% display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas: "img content";
margin-bottom: 1em;
overflow: hidden;
}
.image {
grid-area: img;
background-color: #ffd8a8;
width: 100%;
float: left;
}
.text {
grid-area: content;
padding: 10px;
position: absolute;
top: 10px;
left: 10px;
color: white;
text-shadow: 1px 1px 2px black;
box-sizing: border-box;
}
<div class="media">
<img class="image" src="https://loremflickr.com/500/200" />
<div class="text"><b>This is a media object example.
  We can use grid-template-areas to switch around the image and text part of the media object.</b>   </div>
</div>
I think, if there is just one part of the page at the background of the page, you should create a style. Then look at the backgammon tag select whatever you want,Later, the ID will have it in created anything on the page, for example
Panel, td, div,.... get it there.
You do not need to add any image.
Have you tried position: absolute on the text div?
I figured it out if anyone stumbles across it: (make sure you preview with full page)
#container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 100px;
grid-template-areas: "empty text" "mobile mobile";
}
#container img {
grid-column: 1 / span 2;
grid-row: 1 / span 1;
width: 100%;
overflow: hidden;
}
#container p {
grid-area: text;
color: red;
align-self: center;
justify-self: center;
z-index: 1;
}
#media (max-width: 768px) {
#container p {
grid-area: mobile;
color: red;
align-self: center;
justify-self: center;
z-index: 1;
}
}
<div id="container">
<img src="https://loremflickr.com/500/200">
<p>SOME TEXT OVER IMAGE</p>
</div>

grid-auto-columns does not completely work in Firefox

I don't understand why DIV 3 is not the same size as DIV 1 + DIV 2.
https://codepen.io/anon/pen/vaVqPW
.grid {
display: grid;
grid-auto-columns: 1fr 1fr; /* I also tried 50% 50% */
grid-gap: 20px;
}
Firefox 61 should support css grid according to caniuse
https://caniuse.com/#feat=css-grid
* {
box-sizing: border-box;
}
.grid {
display: grid;
grid-auto-columns: 1fr 1fr;
grid-gap: 20px;
}
.content {
grid-column: 1;
background: red;
}
.sidebar {
grid-column: 2;
background: blue;
}
.grid>* {
/*border: 1px dashed red; */
/* demo only */
}
.box {
width: 50%;
height: 75px;
background-color: black;
color: #fff;
padding: 20px;
position: relative;
float: left;
}
.box100 {
width: 100%;
height: 75px;
color: #fff;
padding: 20px;
}
.box.arrow-left:after {
content: " ";
position: absolute;
left: -15px;
margin-top: -15px;
top: 50%;
border-top: 15px solid transparent;
border-right: 15px solid black;
border-left: none;
border-bottom: 15px solid transparent;
}
<div class="grid">
<div class="content">
<div class="box" style="background:gray">
DIV 1 (50% of column 1)
</div>
<div class="box arrow-left">
DIV 2 (50% of column 1)
</div>
</div>
<div class="sidebar">
<div class="box100">DIV 3 (100% of column 2)</div>
</div>
</div>
<div>
<div class="content" style="background:tomato">
<p>content 4 (100% of column 1 + GAP + 100% of column 2 )</p>
</div>
</div>
Firefox does indeed support CSS Grid (see caniuse.com).
The problem is that Firefox does not appear to support multiple values in grid-auto-columns.
This is your code in Chrome. No problems.
This is your code in Firefox. There's a problem. The code is invalid / not recognized.
It fails in Firefox here, too:
The grid-auto-columns property can take multiple values, per the spec definition. However, Firefox appears to lack support for this set-up. It only accepts a single value.
Your correction to the problem, as stated in your answer and copied below, is simply to switch from implicit columns (grid-auto-columns) to explicit columns (grid-template-columns).
grid: auto-flow dense / 1fr 1fr;
The grid property is a shorthand property that allows you to set all explicit and implicit rules in a single declaration. Your rule above breaks down to this:
So in the end, it appears that a simple switch from grid-auto-columns to grid-template-columns was all you needed.
grid: auto-flow dense / 1fr 1fr;
this seems to solve the Problem!
At the same time deleting the line:
grid-auto-columns: 1fr 1fr;
Pen is updated: https://codepen.io/anon/pen/vaVqPW

can I make a grid item fill up empty column space from a different grid item with CSS grid?

When adjusting the window-size, I want grid item 'C' to fill up the empty space left by grid item 'B' (the profile picture). I used align-self: start; on grid item 'B' to make sure it stays square shaped. Because of this I end up with an 'empty' space when i resize my window. I would like grid item 'C' to fill up this space, with the normal grid-gap in between.
View the problem and code in real life at
https://codepen.io/SanderNiesten/pen/mxaEme?editors=1100 or https://sanderniesten.github.io/
html:
<!-- About Section -->
<section class="about opacity-body" id="about">
<div class= "a" id="about-text">
<h1>Sander Niesten</h1>
<p>Hi! I'm Sander a 29-year-old (on my way to be) webdeveloper from the Haarlem area. End of 2017 I suddenly bumped into my new ♥ : programming! So I decided to give my life a new course and have not regretted it ever since. The last four months have been an epic adventure. A five week bootcamp at Codaisseur, looking into Ruby, Rails, SQL, Javascript, test driven development and so much more. Next, I got my first taste of React through Codecademy and build my first 2 React app's and a cool little minesweeper game. The FreeCodeCamp course is now on my menu. And in the future? Hopefully a traineeship and much more cool stuff to learn!</p>
</div>
<div class="b">
<img id="profile-picture" src="https://source.unsplash.com/random/400x400" alt="">
</div>
<div class="c">
<i class="far fa-file-alt"></i>
</div>
</section>
css:
/* About */
.a {
grid-area: a;
}
.b {
grid-area: b;
}
.c {
grid-area: c;
}
.about
{
display: grid;
background-position: center;
background-size: cover;
grid-auto-rows: minmax(100px, auto);
grid-template-columns: 1fr;
grid-gap: 20px;
grid-template-areas:
"a"
"b"
"c";
}
.about > div {
background-color: rgba(114, 133, 144, 0.95);
padding: 1em;
justify-items: center;
align-items: center;
}
.b {
padding-top: auto;
padding-bottom: auto;
align-self: start;
}
#profile-picture {
display: inline-block;
max-width: 100%;
border-radius: 50%;
box-sizing: border-box;
border-style: solid;
border-width: 4px;
border-color: white;
}
.c {
display: grid;
justify-items: center;
align-items: center;
justify-self: stretch;
}
.fa-file-alt {
font-size: 3.5em;
color: white;
justify-items: center;
align-items: center;
}
#media(min-width: 701px)
{
.about
{
grid-template-columns: repeat(10, 1fr);
grid-template-areas:
"a a a a a a b b b b"
"a a a a a a b b b b"
"a a a a a a c c c c";
}
.grid
{
font-size: 1.1em;
display: grid;
max-width: 920px;
margin: 0 auto;
grid-template-columns: 1fr;
grid-gap: 1em;
}
nav ul
{
display: grid;
padding: 0;
list-style: none;
grid-gap: 20px;
grid-template-columns: 1fr 1fr 1fr;
}
.toggle
{
display: none;
}
}
If I understand your question ok, you want that , when narrowing the screen, but before the media query tekes place, the c element gets adjacent to the square image.
If this is the case, you need to set
.about {
display: grid;
background-position: center;
background-size: cover;
grid-auto-rows: auto auto 1fr; /* changed */
grid-template-columns: 1fr;
grid-gap: 20px;
grid-template-areas:
"a"
"b"
"c";
}
Because you have 3 rows, the image is spanning the first 2, and you want the c element that is on the third row to take up the remaining space
forked codepen
A minimal example showing your request. Hover it to see how it adapts the size
.about {
margin: 10px;
width: 800px;
height: 400px;
border: solid 1px black;
display: grid;
grid-template-areas: "a b" "a c";
grid-template-columns: 60% 40%;
grid-auto-rows: auto 1fr;
transition: width 3s;
}
.about:hover {
width: 400px;
}
.a {
grid-area: a;
}
.b {
grid-area: b;
}
.b2 {
max-width: 100%;
}
.c {
background-color: lightblue;
grid-area: c;
}
<section class="about">
<div class="a">
<p>Hi! I'm Sander a 29-year-old (on my way to be) webdeveloper from the Haarlem area. End of 2017 I suddenly bumped into my new ♥ : programming! So I decided to give my life a new course and have not regretted it ever since. The last four months have been an epic adventure. A five week bootcamp at Codaisseur, looking into Ruby, Rails, SQL, Javascript, test driven development and so much more. Next, I got my first taste of React through Codecademy and build my first 2 React app's and a cool little minesweeper game. The FreeCodeCamp course is now on my menu. And in the future? Hopefully a traineeship and much more cool stuff to learn!</p>
</div>
<div class="b">
<img class="b2" src="https://source.unsplash.com/random/400x400">
</div>
<div class="c">
</div>
</section>

Resources