In CSS grid how to expand child element beyond parent's container - css

I have a CSS grid, say of 3 columns, with parent container located in the middle column, can I somehow expand child to take all three columns? In my code below I want the image area took all three columns, while text took just one:
.grid {
display: grid;
width: 100%;
grid-template-columns: 10% 1fr 10%;
}
.content {
grid-column: 2/3;
}
.image-area {
grid-column: 1/4;
color: #6dae72;
}
<div class="grid">
<div class="content">
<div class="text-area">Some text</div>
<div class="image-area">The picture</div>
</div>
</div>
Would appreciate any help.

Related

How to place nested DIVs in a CSS grid with variable row heights?

I need to place 4 div containers in a 2 by 2 matrix. The width of the columns must be equal (and is therefore fixed), while the height of the rows must adapt itself to the content of the cells (and is therefore variable).
This is simple to do as long as the markup structure looks something like this:
<div class="wrapper">
<div class="cell a1">...</div>
<div class="cell a2">...</div>
<div class="cell b1">...</div>
<div class="cell b2">...</div>
</div>
The corresponding CSS would look like this:
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
}
Unfortunately, my markup (which I cannot change easily) contains the cells in a nested markup structure:
<div class="wrapper">
<div class="container">
<div class="cell a1">...</div>
<div class="cell a2">...</div>
</div>
<div class="container">
<div class="cell b1">...</div>
<div class="cell b2">...</div>
</div>
</div>
As long as the height of the two rows can be equal, declaring .container as secondary grid solves the issue. But since the row height must be adjusted according to the cell content, this doesn't work.
Is there a way to place all four div.cell in the same grid defined by div.wrapper, although they are not direct child elements?
What you are looking for is Subgrid, feature currently (December 2021) only tested on Firefox Nightly.
Info about this CSS attribute (from the Mozilla Web Docs page) :
When you add display: grid to a grid container, only the direct children become grid items and can then be placed on the grid that you have created.
You can "nest" grids by making a grid item a grid container. These grids however are independent of the parent grid and of each other, meaning that they do not take their track sizing from the parent grid. This makes it difficult to line nested grid items up with the main grid.
For example, if you use grid-template-columns: subgrid and the nested grid spans three column tracks of the parent, the nested grid will have three column tracks of the same size as the parent grid.
When the feature will be available and supported by multiple browsers this example below will work (I guess):
html, body {
width: 100%;
height: 100%;
margin: 0;
}
.wrapper {
display: grid;
height: 100vh;
width: 100vw;
background: grey;
grid-auto-flow: rows;
grid-template-columns: auto auto;
grid-template-rows: auto auto;
}
.container {
display: grid;
grid-column: 1 / 3;
grid-row: 1 / 3;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
}
.a1{
background-color: blue;
grid-row: 1;
grid-column: 1;
}
.a2{
background-color: yellow;
grid-row: 1;
grid-column: 2;
}
.b1 {
background-color: red;
grid-row: 2;
grid-column: 1;
}
.b2 {
background-color: green;
grid-row: 2;
grid-column: 2;
}
<div class="wrapper">
<div class="container a">
<div class="cell a1">A1</div>
<div class="cell a2">A2</div>
</div>
<div class="container a">
<div class="cell b1">B1</div>
<div class="cell b2">B2</div>
</div>
</div>
And will render something like this :

CSS Grid layout change width of specific columns with class

.grid {
display: grid;
grid-template-columns: 80% 20%;
}
<div class="grid">
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item-special"></div>
<div class="grid-item-special"></div>
</div>
So far the above is straight forward, each row will contain two columns with respective widths of 80% and 20%
However I wish to adapt the above to make it responsive. On smaller screens any div with class "grid-item" will occupy 100% of the width (so each row will contain one column)
The above is not a problem, however further to the above I want any div with the class "grid item-special" to occupy 50% of the width.
The image shows what I am attempting to accomplish:
I need to avoid changing the html markup if possible.
Any ideas would be welcomed.
You can create media query and change grid on smaller screen
.grid {
display: grid;
grid-template-columns: 80% 20%;
text-align: center;
}
.grid-item, .grid-item-special{
border: 1px solid black;
}
#media (max-width: 400px) {
.grid {
grid-template-columns: auto;
}
.grid-item {
grid-column: span 2;
}
}
<div class="grid">
<div class="grid-item">11</div>
<div class="grid-item">11</div>
<div class="grid-item-special">22</div>
<div class="grid-item-special">22</div>
</div>

min-content with justify-self: right?

Is it possible with CSS3 grid to create such a layout?
All of the elements should be as wide as their content. And the last two elements should be right-aligned.
However, the way I've tried does not work. As soon as a column has min-content, the justify-self property doesn't do anything.
.grid {
display: grid;
grid-template-areas: "first second third";
grid-template-columns: min-content min-content min-content;
}
.first {
grid-area: first;
}
.second {
grid-area: second;
justify-self: right; /* doesn't work */
}
.third {
grid-area: third; /* doesn't work */
}
<div class="grid">
<div class="first">first</div>
<div class="second">second</div>
<div class="third">third</div>
</div>
This is only a downsized version of a much more complex layout, therefore:
I'm not looking for workarounds like creating wrappers
Stretching .first is not an option because there will be calculations on that element
The reason I chose grid over flex is because of the gaps
Using flexbox may be more appropriate? note the margin-right on the first element in container 1, and margin-left on the second element in container 2. auto margins are quite powerful in flex containers.
.container-1,
.container-2 {
display: flex;
background: lightgray;
}
.item {
width: max-content;
margin: 1em;
padding: 1em;
background: white;
}
.container-1 .item-1 {
margin-right: auto;
}
.container-2 .item-2 {
margin-left: auto;
}
<div class="container-1">
<div class="item item-1">
item 1
</div>
<div class="item item-2">
item 2
</div>
<div class="item item-3">
item 3
</div>
</div>
<div class="container-2">
<div class="item item-1">
item 1
</div>
<div class="item item-2">
item 2
</div>
<div class="item item-3">
item 3
</div>
</div>

css grid align vertically and horizontally without disturbing background color or image

i created .container with some color & in that container header with some other color and text. now i want to center text. i am able to do that with grid but problem is my header color (background color of header) shrink to vertically and horizontally center too. i want only text to get in center not the color. hope i explained clearly. plz explain me how i can achieve that.
(
i am using visual studio. align-item align-content align-self(on header)justify-item,content,self nothing working for me plz clear my confusion
i need only text in center if i put image or logo that in center. i dont want background image to be compromise and i wanna use grid only.
i tried 6 grid commands align-item align-content align-self(on header)justify-item,content,self nothing working for me plz clear my confusion.
i am using visual studio. align-item align-content align-self(on header)justify-item,content,self nothing working for me plz clear my confusion
<div class="container">
<div class="header">This is header</div>
<div class="small-box-1">Small-Box1</div>
<div class="small-box-2">Small-Box2</div>
<div class="small-box-3">Small-Box3</div>
<div class="main-content">Main Content</div>
<div class="side-bar">Side-Bar</div>
<div class="footer">footer</div>
</div>
</div>
To center element on the grid and avoid them to shrink, you will need to set again a grid system on your children You can use flex or grid .
examples (might not be your grid, but needed a base that you did not provide, if that does not answer your question then, please, clarify your question)
Flex can be used on the grid children to allow centering alignement.
.container> div {
display:flex;
align-items:center;
justify-content:center;
background:tomato;
border:solid;
}
/* reconstruction of a grid */
.container {
display:grid;
grid-template-columns:repeat(4,1fr);
grid-auto-rows: minmax(150px,1fr);
grid-gap:1em;
}
.container .header, .container .footer {
background:lightblue;
grid-column:span 4;
}
.small-box-1 {
grid-column:2;
}
.main-content{
grid-column:2 / span 3
}
.side-bar {
grid-column:1;
grid-row:2 / span 2;
}
<div class="container">
<div class="header">This is header</div>
<div class="small-box-1">Small-Box1</div>
<div class="small-box-2">Small-Box2</div>
<div class="small-box-3">Small-Box3</div>
<div class="main-content">Main Content</div>
<div class="side-bar">Side-Bar</div>
<div class="footer">footer</div>
</div>
Grid can also be used on the grid children to allow centering alignement.
.container>div {
display: grid;
align-items: center;
justify-content: center;
background: tomato;
border: solid;
}
/* reconstruction of a grid */
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(150px, 1fr);
grid-gap: 1em;
}
.container .header,
.container .footer {
background: lightblue;
grid-column: span 4;
}
.small-box-1 {
grid-column: 2;
}
.main-content {
grid-column: 2 / span 3
}
.side-bar {
grid-column: 1;
grid-row: 2 / span 2;
}
<div class="container">
<div class="header">This is header</div>
<div class="small-box-1">Small-Box1</div>
<div class="small-box-2">Small-Box2</div>
<div class="small-box-3">Small-Box3</div>
<div class="main-content">Main Content</div>
<div class="side-bar">Side-Bar</div>
<div class="footer">footer</div>
</div>

How to make a column span full width when a second column is not there? (CSS Grid)

I know there are similar questions but this is specifically asking how to do this using CSS Grid Layout.
So we have this basic grid setup:
HTML (with sidebar):
<div class="grid">
<div class="content">
<p>content</p>
</div>
<div class="sidebar">
<p>sidebar</p>
</div>
</div>
CSS:
.grid {
display: grid;
grid-template-columns: 1fr 200px;
}
To create a layout that looks something like this:
| content | sidebar |
If the page doesn't have a sidebar though, ie. the html looks like this but with the same CSS:
HTML (no sidebar):
<div class="grid">
<div class="content">
<p>content</p>
</div>
</div>
The page layout looks like this (dashes represent empty space)
| content | ------- |
I know why it does that, the grid column is still defined in the grid-template-columns rule.
I'm just wondering how to tell the grid that if there is no content, then fill the remaining space similar to how flex-grow works for flexbox.
The desired result would look like this if no sidebar is present.
| content |
Don't define the columns explicitly with grid-template-columns.
Make the columns implicit instead and then use grid-auto-columns to define their widths.
This will allow the first column (.content) to consume all space in the row when the second column (.sidebar) doesn't exist.
.grid {
display: grid;
grid-auto-columns: 1fr 200px;
}
.content {
grid-column: 1;
}
.sidebar {
grid-column: 2;
}
.grid > * {
border: 1px dashed red; /* demo only */
}
<p>With side bar:</p>
<div class="grid">
<div class="content">
<p>content</p>
</div>
<div class="sidebar">
<p>sidebar</p>
</div>
</div>
<p>No side bar:</p>
<div class="grid">
<div class="content">
<p>content</p>
</div>
</div>
You can get closer by using content sizing keywords, something like:
.grid {
display: grid;
grid-template-columns: 1fr fit-content(200px);
}
.sidebar {
width: 100%;
}
The fit-content keyword will look at the size of the content and act like max-content until it gets to the value you pass in.
In reality you probably wouldn't need to stick a size on sidebar as the content is likely to dictate a size of at least 200 pixels (for example) but you can play around with this.
I think I know the definitive answer to this question now. The problem with the answers so far is that they don't explain how to handle a sidebar that is on the left side of the main content (mainly because I didn't ask for it in the original question).
<div class="grid">
<nav>
<p>navigation</p>
</nav>
<main>
<p>content</p>
</main>
<aside>
<p>sidebar</p>
</aside>
</div>
You can use this CSS:
.grid {
display: grid;
grid-template-columns: fit-content(200px) 1fr fit-content(200px);
}
nav, aside {
width: 100%;
}
/* ensures that the content will always be placed in the correct column */
nav { grid-column: 1; }
main { grid-column: 2; }
aside { grid-column: 3; }
This is also a good use case for grid-areas
.grid {
display: grid;
grid-template-columns: fit-content(200px) 1fr fit-content(200px);
grid-template-areas: "nav content sidebar";
}
nav, aside {
width: 100%;
}
/* ensures that the content will always be placed in the correct column */
nav { grid-area: nav; }
main { grid-area: content; }
aside { grid-area: sidebar; }
An IE compatible version would look like this:
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: auto 1fr auto;
grid-template-columns: auto 1fr auto;
}
nav, aside {
width: 100%; /* Ensures that if the content exists, it takes up max-width */
max-width: 200px; /* Prevents the content exceeding 200px in width */
}
/* ensures that the content will always be placed in the correct column */
nav {
-ms-grid-column: 1;
grid-column: 1;
}
main {
-ms-grid-column: 2;
grid-column: 2;
}
aside {
-ms-grid-column: 3;
grid-column: 3;
}

Resources