How do I use calc() with min-content? - html

I have a grid layout which can be simplified like this.
What I want to achieve is the .side should take whatever space the content needs to by default using min-content, but user can enlarge it by increasing the --size custom css property.
I tried calc(min-content + var(--size)) but it doesn't work. I can't assign a specific value like calc(100px + var(--size)) since the original size should be determined by its content.
What is the best approach to achieve such a feature?
* {
box-sizing: border-box;
}
body {
overflow: hidden;
margin: 0;
}
.container {
--size: 10px;
width: 100vw;
height: 100vh;
display: grid;
grid-template-areas:
"l t"
"l b";
/* doesn't work */
/* grid-template-columns: calc(min-content + var(--size)) 1fr; */
grid-template-columns: min-content 1fr;
grid-template-rows: 1fr 1fr;
}
.container > * {
border: solid 1px black;
}
.side {
grid-area: l;
}
.top {
grid-area: t;
}
.bottom {
grid-area: b;
}
<section class="container">
<div class="side">This should have a 10px gutter on the right</div>
<div class="top">Top</div>
<div class="bottom">Bottom</div>
</section>

Use width:calc(100% + var(--size)) for the grid item. This will create an overflow that you can rectify by adding a gap:
* {
box-sizing: border-box;
}
body {
overflow: hidden;
margin: 0;
}
.container {
--size: 20px;
height: 100vh;
display: grid;
grid-template-areas:
"l t"
"l b";
/* doesn't work */
/* grid-template-columns: calc(min-content + var(--size)) 1fr; */
grid-template-columns: min-content 1fr;
grid-template-rows: 1fr 1fr;
column-gap:var(--size);
}
.container > * {
border: solid 1px black;
}
.side {
grid-area: l;
width:calc(100% + var(--size));
}
.top {
grid-area: t;
}
.bottom {
grid-area: b;
}
<section class="container">
<div class="side">This should have a 10px gutter on the right</div>
<div class="top">Top</div>
<div class="bottom">Bottom</div>
</section>

Related

how to use css grid to display components at particular area

here's my html code
<div>
<div id="navbar" class="box">Navbar</div>
<div id="sidenav " class="box">Side Navbar</div>
<div id="main " class="box">Main</div>
<div id="footer " class="box">Footer</div>
</div>
and here's my scss code
div{
display: grid;
width:100%;
height: 100%;
grid-template-columns: 25% 75% 25%;
grid-gap: 15px;
grid-template-rows:25% 50% 25% ;
// grid-gap: 15px;
grid-template-areas:
"hd hd hd "
"sd ma ma "
"ft ft ft ";
.box{
display: flex;
// text-align: center;
border: 3px solid red;
/* width:150px;
height: 150px; */
margin: auto;
align-items: center;
justify-content: center;
}
#navbar{
grid-area: hd;
}
#sidenav{
grid-area: sd;
}
#main{
grid-area: ma;
}
#footer{
grid-area: ft;
}
}
the problem is the footer div doesn't display in the bottom here's a screenshot
what i want is to make the footer display at the bottom so what seems to be the problem here
There are some issues that I found in your code which makes the layout little wonky.
grid-template-columns: 25% 75% 25%;
The column total is more than 100%, so it will not work perfectly.
I would highly recommend you to use a CSS grid generator online like https://grid.layoutit.com/
For your layout, I would also not recommend structure 3x3 (columns and rows) - As from the image you shared above it looks like the following
1 row - For "Navbar" (this doesnt need any sub columns)
1 row - For Content -> this has 2 columns 1 for "SideNav" and 1 for "Main"
1 row - For "Footer" (again you dont need sub columns)
Based on this your HTML structure will end up looking like
<div class="container">
<div class="navbar">Navbar</div>
<div class="Content">
<div class="SideNav">Side Nav</div>
<div class="Main">Main</div>
</div>
<div class="Footer">Footer</div>
</div>
And your CSS will look like this
body{
padding: 0;
margin: 0;
}
.container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 25% 50% 25%;
gap: 0px 0px;
grid-template-areas:
"navbar"
"Content"
"Footer";
}
.navbar {
grid-area: navbar;
background-color: #f5f5f5;
padding: 16px;
text-align: center;
}
.Content {
display: grid;
grid-template-columns: 360px 1fr;
grid-template-rows: 1fr;
gap: 0px 0px;
grid-template-areas:
"SideNav Main";
grid-area: Content;
}
.SideNav {
grid-area: SideNav;
background-color: #e5e5e5;
padding: 16px;
}
.Main {
grid-area: Main;
background-color: salmon;
padding: 16px;
}
.Footer {
grid-area: Footer;
background-color: #d5d5d5;
padding: 16px;
text-align: center;
}
Here, if you check the code well, the container has 3 rows (25% - navbar, 50% - content, 25% - footer)
And then content has 2 columns (360px - Sidenav, 1fr - Main)
Hope this helps :)
You can also see the code live on my codepen : https://codepen.io/raunaqpatel/pen/WNyQqmm
Or here:
body{
padding: 0;
margin: 0;
}
.container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 25% 50% 25%;
gap: 0px 0px;
grid-template-areas:
"navbar"
"Content"
"Footer";
}
.navbar {
grid-area: navbar;
background-color: #f5f5f5;
padding: 16px;
text-align: center;
}
.Content {
display: grid;
grid-template-columns: 360px 1fr;
grid-template-rows: 1fr;
gap: 0px 0px;
grid-template-areas:
"SideNav Main";
grid-area: Content;
}
.SideNav {
grid-area: SideNav;
background-color: #e5e5e5;
padding: 16px;
}
.Main {
grid-area: Main;
background-color: salmon;
padding: 16px;
}
.Footer {
grid-area: Footer;
background-color: #d5d5d5;
padding: 16px;
text-align: center;
}
<div class="container">
<div class="navbar">Navbar</div>
<div class="Content">
<div class="SideNav">Side Nav</div>
<div class="Main">Main</div>
</div>
<div class="Footer">Footer</div>
</div>

Need assist with CSS grid layout of cards

I have this grid over here:
and i want the first big card to take the whole height of the wrapper and remain the same width, while the bottom two cards go to the right, somehow like this:
here's my css/html code where item-1 is the bigger card on the top-left:
.cards-wrapper {
background-color: #43cbff;
width: 1240px;
height: 380px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-gap: 20px;
#media (min-width: 30em) {
grid-template-columns: 1fr 1fr;
}
#media (min-width: 60em) {
grid-template-columns: repeat(4, 1fr);
}
}
.cards {
display: flex;
flex-direction: column;
min-height: 100%;
position: relative;
top: 0;
background-color: aquamarine;
border: 1px solid lightgrey;
border-radius: 8px;
}
.item-1 {
#media (min-width: 60em) {
grid-column: 1 / span 2;
h1 {
font-size: 24px;
}
}
}
You can keep the grid layout and use grid-template-areas to make that first item take up the full height whilst retaining its existing width.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-auto-columns: 1fr;
grid-auto-rows: 1fr;
gap: 8px 8px;
grid-auto-flow: row;
grid-template-areas:
"one one two three"
"one one four five";
}
.container * {
background: orange;
}
.one { grid-area: one; }
.two { grid-area: two; }
.three { grid-area: three; }
.four { grid-area: four; }
.five { grid-area: five; }
<div class="container">
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>
</div>
Flex version
I dont know you entire structure and your requirement. But by using only flexbox you can archive this also quite easy.:
.cards-wrapper {
background: gray;
}
.flex {
display: flex;
gap:5px;
}
.left, .right {
width: 50%;
}
.right {
flex-wrap: wrap;
justify-content: center;
}
.right > div {
width: 49,2%;
background-color: lightgreen;
height:100px;
}
.big {
background-color: green;
width: 100%;
}
<div class="cards-wrapper flex">
<div class="left flex">
<div class="big">BIG</div>
</div>
<div class="right flex">
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
</div>

grid layout with resize horizontal not resizing columns [duplicate]

This question already has an answer here:
resize column across multiple rows using html grid layout
(1 answer)
Closed 1 year ago.
I've got a grid layout and I'm using resize: horizontal on one. It lets me resize the box but it doesn't resize the other columns as I would expect it to.
html,
body,
.main {
height: 100%;
margin: 0;
}
.main {
display: grid;
grid-template-columns: minmax(100px, 200px) 1fr;
grid-template-rows: 50px 1fr;
gap: 2px 2px;
grid-auto-flow: row;
grid-template-areas: "header-box header-box" "left-box main-box";
}
.header-box {
background-color: lightblue;
grid-area: header-box;
overflow: hidden;
}
.left-box {
background-color: lightgreen;
grid-area: left-box;
resize: horizontal;
overflow: auto;
}
.main-box {
background-color: lightpink;
grid-area: main-box;
overflow: auto;
}
<div class="main">
<div class="header-box">header box</div>
<div class="left-box">left box</div>
<div class="main-box">main box</div>
</div>
minmax(100px, 200px) is as good as 200px if you want shrinking behavior change to minmax(100px, 1fr)
If you want the grid to responsed to the content rather than the available width of it's own parent change to display: inline-grid;
html,
body,
.main {
height: 100%;
margin: 0;
}
.main {
display:inline-grid;
grid-template-columns: minmax(100px, 1fr) 1fr;
grid-template-rows: 50px 1fr;
gap: 2px 2px;
grid-auto-flow: row;
grid-template-areas: "header-box header-box" "left-box main-box";
}
.header-box {
background-color: lightblue;
grid-area: header-box;
overflow: hidden;
}
.left-box {
background-color: lightgreen;
grid-area: left-box;
resize: horizontal;
overflow: auto;
}
.main-box {
background-color: lightpink;
grid-area: main-box;
overflow: auto;
}
<div class="main">
<div class="header-box">header box</div>
<div class="left-box">left box</div>
<div class="main-box">main box</div>
</div>

CSS Grid container with dynamic amount of columns

I have a grid container with those settings -
display: grid;
grid-template-columns: 1fr 1fr 2fr repeat(4, 1fr) 2rem;
grid-auto-flow: column;
grid-auto-columns: 1fr;
height: 100%;
width: 100%;
I initially set the container for 8 columns. The issue is that in some cases will be 9 columns. The extra column will be added to be the 3rd and not at the end, so after the insertion of the extra column the grid should be -
grid-template-columns: 1fr 1fr 1fr 2fr repeat(4, 1fr) 2rem;
Here is the code
function addColumn(){
var g = document.querySelector(".my_grid");
var div = document.createElement("div");
div.setAttribute("id", "column9");
g.appendChild(div);
}
body{
margin:0;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.my_grid {
display: grid;
grid-template-columns: 1fr 1fr 2fr repeat(4, 1fr) 2rem;
grid-auto-flow: column;
grid-auto-columns: 1fr;
height: 100%;
width: 100%;
}
.my_grid div{
box-sizing: border-box;
transition: .5s linear all;
}
#column1 { background: #0000 }
#column2 { background: #0001 }
#column3 { background: #0002 }
#column4 { background: #0003 }
#column5 { background: #0004 }
#column6 { background: #0005 }
#column7 { background: #0006 }
#column8 { background: #0007 }
#column9 { background: #0008; border:1px solid red; }
button {
position: fixed;
top: 0;
left: 0;
height: 40px;
width: 100px;
}
<div class="my_grid">
<div id="column1"></div>
<div id="column2"></div>
<div id="column3"></div>
<div id="column4"></div>
<div id="column5"></div>
<div id="column6"></div>
<div id="column7"></div>
<div id="column8">
2rem
</div>
</div>
<button onclick="addColumn()">Add Column</button>
So the question is how to handle this situation? I tried to set it dynamically with auto-fill but it doesn't work.
If I get this right you want to add a dynamic div or there is a div that is added to the end. Here is how you can make it be in the third place.
body {
margin: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.my_grid {
display: grid;
grid-template-columns: 1fr 1fr 2fr repeat(4, 1fr) 2rem;
grid-auto-flow: column;
grid-auto-columns: 1fr;
height: 100%;
width: 100%;
}
.my_grid div {
box-sizing: border-box;
transition: 0.5s linear all;
}
#column1 {
background: #0000;
}
#column2 {
background: #0001;
}
#column3 {
background: #0002;
}
#column4 {
background: #0003;
}
#column5 {
background: #0004;
}
#column6 {
background: #0005;
}
#column7 {
background: #0006;
}
#column8 {
background: #0007;
}
#column9 {
background: red;
border: 1px solid red;
grid-column: 3 / 4;
}
<div class="my_grid">
<div id="column1"></div>
<div id="column2"></div>
<div id="column3"></div>
<div id="column4"></div>
<div id="column5"></div>
<div id="column6"></div>
<div id="column7"></div>
<div id="column8"></div>
<div id="column9"></div>
</div>
You can rely on order property and the creation of implicit extra column at the start. The trick is to use nth-child to consider the case where there is 9 items in order to:
Place the first item outside the explicit grid. It will use the implicit one (1fr will be added at the start)
Place the last item column9 at the beginning.
Force the item column2 to be before column9
function addColumn(){
var g = document.querySelector(".my_grid");
var div = document.createElement("div");
div.setAttribute("id", "column9");
g.appendChild(div);
document.querySelector("button").style.display="none";
}
body{
margin:0;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.my_grid {
display: grid;
grid-template-columns: 1fr 1fr 2fr repeat(4, 1fr) 2rem;
grid-auto-flow: column;
grid-auto-columns: 1fr; /* our implicit column */
height: 100%;
width: 100%;
}
.my_grid div{
box-sizing: border-box;
transition: .5s linear all;
}
#column1 { background: #0000 }
#column2 { background: #0001 }
#column3 { background: #0002 }
#column4 { background: #0003 }
#column5 { background: #0004 }
#column6 { background: #0005 }
#column7 { background: #0006 }
#column8 { background: #0007 }
#column9 {
background: #0008;
border:1px solid red;
order:-1; /* place at the start */
}
/* The below will trigger only with 9 columns */
#column1:first-child:nth-last-child(9) {
background:green;
grid-column:-10; /* place before everything outisde the explicit grid */
}
#column2:nth-child(2):nth-last-child(8) {
background:blue;
order:-1; /* place before column9*/
}
button {
position: fixed;
top: 0;
left: 0;
height: 40px;
width: 100px;
}
<div class="my_grid">
<div id="column1"></div>
<div id="column2"></div>
<div id="column3"></div>
<div id="column4"></div>
<div id="column5"></div>
<div id="column6"></div>
<div id="column7"></div>
<div id="column8">
2rem
</div>
</div>
<button onclick="addColumn()">Add Column</button>

Avoiding dead DIVs in an HTML grid

The objective is to insert side margins for wider screens, while keeping the header span the entire width.
Normally we'd write
.inner {
margin: 0 5%;
}
to get such margins, but it turns out that HTML grids are so flexible that they make side margins possible through dead grid DIVs.
But somehow using dead DIVs does not seem quite right. Is there a way to obtain side margins within a grid. I see how this can be done with a blend of flex and grid. Here I'm wondering if it can be done with grids alone.
body {
height: 100vh; margin: 0; display: flex;
}
.outer{
margin: 5px; border: 5px; padding: 5px;
display: flex;
flex-grow: 1;
}
.inner {
flex-grow: 1;
margin: 5px; border: 5px; padding: 5px; grid-gap: 5px;
display: grid;
grid-template-rows: 100px 5fr 100px;
grid-template-columns: 1fr;
grid-template-areas: "header" "content" "side";
}
#media screen and (min-width: 600px) {
.inner {
grid-template-rows: 100px 6fr;
grid-template-columns: 5fr 100px;
grid-template-areas:
"header header"
"content side";
}
}
#media screen and (min-width: 800px) {
.inner {
grid-template-rows: 100px 6fr;
grid-template-columns: 1fr 5fr 100px 1fr;
grid-template-areas:
"header header header header"
"leftmargin content side rightmargin";
}
}
.box {
padding: 10px; margin: 5px;
border: 5px solid #444;
background-color: #eee;
font-size: 150%;
position: relative;
}
.header { grid-area: header; }
.content { grid-area: content; }
.side { grid-area: side; }
.leftmargin { grid-area: leftmargin; }
.rightmargin { grid-area: rightmargin; }
<div class="outer">
<div class="inner">
<div class="box header">Header</div>
<div class="box content">Content</div>
<div class="box side">Side</div>
</div>
</div>
Use dots (.) to declare empty grid areas:
grid-template-areas:
"header header header header"
". content side .";
Example:
body {
height: 100vh;
margin: 10px;
}
.inner {
display: grid;
grid-template-rows: 100px 5fr 100px;
grid-template-columns: 1fr;
grid-template-areas: "header" "content" "side";
grid-gap: 5px;
}
#media screen and (min-width: 600px) {
.inner {
grid-template-rows: 100px 6fr;
grid-template-columns: 5fr 100px;
grid-template-areas:
"header header"
"content side";
}
}
#media screen and (min-width: 800px) {
.inner {
grid-template-rows: 100px 6fr;
grid-template-columns: 5% 5fr 100px 5%;
grid-template-areas:
"header header header header"
". content side .";
}
}
.box {
padding: 10px; margin: 5px;
border: 5px solid #444;
background-color: #eee;
font-size: 150%;
position: relative;
}
.header { grid-area: header; }
.content { grid-area: content; }
.side { grid-area: side; }
<div class="inner">
<div class="box header">Header</div>
<div class="box content">Content</div>
<div class="box side">Side</div>
</div>