I am trying to fill the empty field (column 1, row 2) with standard content (i.e. "NOT AVAILABLE"). I was not available to come up with any appropriate solution within CSS - tried a few approaches with CSS selectors, but without any luck.
How do I achieve this, without using JS or adding an empty element in the HTML source? The reason I don't want to use other technologies is because we cannot alter the original HTML content.
.grid{
display: grid;
grid-template-columns: 1fr 1fr;
}
.itemA{
grid-column: 1;
border: 1px solid black;
}
.itemB{
grid-column: 2;
border: 1px solid black;
}
<div class="grid">
<div class="itemA">Content A</div>
<div class="itemB">Content B</div>
<div class="itemB">Content C</div>
</div>
In CSS Grid, CSS pseudo-elements are treated as grid items. (This is the equivalent behavior of pseudo-elements in flexbox, which are flex items.)
Therefore, using CSS alone, you can achieve your goal:
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
}
.grid::before {
content: "NOT AVAILABLE";
grid-column: 1;
grid-row: 2;
}
.itemA {
grid-column: 1;
border: 1px solid black;
}
.itemB {
grid-column: 2;
border: 1px solid black;
}
<div class="grid">
<div class="itemA">Content A</div>
<div class="itemB">Content B</div>
<div class="itemB">Content C</div>
</div>
Related
I am new to CSS grid and trying to implement the second row only in the below picture.
I've tried to create six sections but have the second section spread out longer. For example I've tried:
grid-column: 2 / span 5;
But it seems to push the last four section to the next line cause it to wrap which I do not want.
my unsuccessful code:
.container {
border: solid black 3px;
height: 100px;
display: grid;
grid-template-columns: repeat(6, 1fr);
}
.item {
border: solid skyblue 1px;
}
.item:nth-of-type(2) {
/* grid-column: 2 / span 5; */
}
<div class="container">
<div class="item"></div>
<div class="item">Totals</div>
<div class="item">6000</div>
<div class="item">-</div>
<div class="item">194</div>
<div class="item">12.5%</div>
</div>
Try auto on the columns, with 1fr on the flexible one.
.container {
border: solid black 3px;
height: 100px;
display: grid;
grid-template-columns: minmax(100px, auto) 1fr repeat(4, minmax(100px, auto));
}
.item {
border: solid skyblue 1px;
}
<div class="container">
<div class="item"></div>
<div class="item">Totals</div>
<div class="item">6000</div>
<div class="item">-</div>
<div class="item">194</div>
<div class="item">12.5%</div>
</div>
jsFiddle demo
Try adding grid-auto-flow: column; to your .container and change grid-column: 2 / span 5; to grid-column: 2 / span 3;
Is it possible to use CSS grid to auto-fit the columns in a row to always take up the whole width?
I know this would be possible if you knew the number of columns, but is it possible with a dynamic number of columns?
Image for reference of what I'd like to achieve.
column example image
This is what I have so far, but you can see that the lower row item doesn't take up all the row width.
.wrapper {
display: grid;
grid-template-columns: 200px 200px;
column-gap: 20px;
}
.grid {
border: solid #FF8181 1px;
display: grid;
grid-template-rows: 40px repeat(8, minmax(0, 1fr));
width: 200px;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.row-item {
background: #FFC555;
border: 1px solid #835600;
width: 100%;
height: 40px;
}
.item-1, .item-1 {
grid-row: 2 / span 1;
}
.item-2 {
grid-row: 6 / span 1;
font-size: 12px;
}
<div class='wrapper'>
<div class='grid'>
<div class='row-item item-1'></div>
<div class='row-item item-1'></div>
<div class='row-item item-2'>I'm too short</div>
</div>
<div class='grid'>
<div class='row-item item-1'></div>
<div class='row-item item-1'></div>
<div class='row-item item-1'></div>
<div class='row-item item-2'>Should be the whole width</div>
</div>
</div>
you can stretch a element in a grid over the whole width by using:
grid-column: 1 / all;
or
grid-column: 1 / -1;
unfortunately does it affect the other elements in the same grid.
A solution like "span last-column" doesnt exist yet, but is already discussed: https://github.com/w3c/csswg-drafts/issues/2402
Maybe they will implement the function soon. Good luck anyways
What I need doesn't exist yet. This does indeed look like the latest update:
A solution like "span last-column" doesnt exist yet, but is already
discussed: https://github.com/w3c/csswg-drafts/issues/2402
I calculated overlapping grid items and rendered items in subgrids based on this answer:
Group multiple overlapping timeblocks that may not have a direct overlap
With js its different.
Find the grid
Get the Style of the Grid
Filter the Style of the Grid for grid-template-columns
Set the Element grid-column to the number of columns
Your code will look like this:
window.addEventListener("DOMContentLoaded", function(){
// find the elemen by the class and safe it as grid
let grid = document.querySelector(".grid")
// sage the style of the element
const gridComputedStyle = window.getComputedStyle(grid);
// get the grid-template-columns style poperty of the element and format them to a useful value
const gridColumnCount = gridComputedStyle.getPropertyValue("grid-template-columns").split(" ").length
// log for debug
console.log(gridColumnCount)
// set the column style of the element to the span of the variable
document.getElementById("item-2").style.gridColumn = "1 / span " + gridColumnCount;
// set the row style because it got overwritten by the line above
document.getElementById("item-2").style.gridRow = "6 / span " + gridColumnCount;
})
note that i have changed your html and css too:
html:
<div class='grid'>
<div class='row-item item-1'></div>
<div class='row-item item-1'></div>
<div class='row-item item-1'></div>
<div class="row-item" id="item-2">whole width</div>
</div>
Just deleted the wrapper for a better overview
CSS:
.grid {
border: solid #FF8181 1px;
display: grid;
grid-template-rows: repeat(8, minmax(0, 1fr));
width: 300px;
grid-template-columns: repeat(auto, minmax(0, 1fr));
}
.row-item {
background: #FFC555;
border: 1px solid #835600;
width: 100%;
height: 40px;
}
.item-1, .item-1 {
grid-row: 2;
}
.item-2 {
grid-row: 5;
font-size: 12px;
}
I had to change the grid-template-value of grid from auto-fit to auto. Otherwise there would be a bug when counting the columns
can someone please tell me why the 3rd div is looking that way instead of being right under the 1st div? And what would I need to write in my CSS file to make the 3rd div positioned right under the 1st one?
This is the HTML:
<div class="div-main">
<div class="div-1">
1
</div>
<div class="div-2">
2
</div>
<div class="div-3">
3
</div>
</div>
This is the CSS:
.div-main {
border: 5px solid yellow;
padding: 15px;
}
.div-1 {
border: 1px solid black;
padding: 15px;
width: 30%;
height: 30vh;
display: inline-block;
}
.div-2 {
border: 1px solid black;
padding: 15px;
width: 69%;
height: 50vh;
display: inline-block;
}
.div-3 {
border: 1px solid black;
padding: 15px;
width: 30%;
height: 30vh;
display: inline-block;
}
Why this is happening?
By default, the block elements, whether they are block or inline-block, will fill all the available space in the row, so if the blocks should have an overlapping situation, you can't achieve it with block approaches.
How to solve it?
With the CSS grid approach, you can make sure how each element should be positioned in your box. You can specify how your columns should be distributed by using the grid-template-columns, and how your rows should do it, with the grid-auto-rows property. You can also ensure how much of your current available space should be filled with the children by using grid-column and grid-row on each child.
The grid approach:
.div-main {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
grid-auto-rows: minmax(100px, auto);
}
.div-1, .div-2, .div-3 {
border: 1px solid black;
}
.div-1 {
grid-column: 1 / 2;
grid-row: 1;
}
.div-2 {
grid-column: 2 / 4;
grid-row: 1 / 3;
}
.div-3 {
grid-column: 1;
grid-row: 2 / 3;
}
<div class="div-main">
<div class="div-1">1</div>
<div class="div-2">2</div>
<div class="div-3">3</div>
</div>
How the above code works?
In this example by default,
I distributed the available space for the column into 3 even blocks (grid-template-columns: repeat(3, 1fr)).
I set the minimum of each row to be 100px and allow them to grow if other blocks in the container want them to (grid-auto-rows: minmax(100px, auto)).
At last, I set the children to fill the available space the way I wanted (grid-column: *; grid-row: *;).
NOTE1: If in any case you want to make the third child gets bigger in height in comparison to the second child you can change the second part of grid-row: 2 / 3; to a bigger number like grid-row: 2 / 4;.
.div-main {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
grid-auto-rows: minmax(100px, auto);
}
.div-1, .div-2, .div-3 {
border: 1px solid black;
}
.div-1 {
grid-column: 1 / 2;
grid-row: 1;
}
.div-2 {
grid-column: 2 / 4;
grid-row: 1 / 3;
}
.div-3 {
grid-column: 1;
grid-row: 2 / 4;
}
<div class="div-main">
<div class="div-1">1</div>
<div class="div-2">2</div>
<div class="div-3">3</div>
</div>
NOTE2: You can learn more about how CSS grid works in the CSS-tricks website with more examples.
Here I don't directly say why; I think others have done a great job there. Here I show how you can place items in columns in a container, and then forced some sizing to show the effect of doing that within individual blocks - and why sizing to the containing element might be more desirable at times.
I added a left/right block to illustrate the effect of creating logical groups of elements to work with by simply wrapping them in a group-left and group-right thus if you change grid-template-columns: minmax(150px, 30%) 30%; to grid-template-columns: minmax(150px, 30%) 1fr; the right group takes up whatever is remaining - a typical left/right layout where you have say links in the left group for example.
The only difference between the to major containers here is the content of each and those styles added to those contained elements.
.parent {
display: grid;
grid-template-columns: minmax(150px, 30%) 30%;
}
.group-left {
border: solid purple 3px;
background-color: #77008822;
}
.group-left>* {
margin: 1rem;
}
.group-right {
border: solid orange 3px;
}
.content-block {
/* just here to center the text in both directions */
display: grid;
place-items: center;
border: 1px solid;
}
/* below here is now just color and border styling and some forced sizing */
.div-main {
border: 5px solid yellow;
/* padding: 15px;*/
}
.div-1 {
border: 1px solid black;
/* force a height */
height: 30vh;
}
.div-2 {
border: 1px solid black;
/* force a height */
height: 50vh;
background-color: #eeffdd;
/* this can make the second block wider and potentially overlap the next column */
width: 20em;
}
.div-3 {
border: 1px solid black;
/* force a height */
height: 30vh;
}
.forced-height {
height: 30vh;
background-color: #44ddff33;
}
.img-force {
border: dashed 2px cyan;
width: 50%;
height: 30vh;
}
<div class="parent div-main">
<div class="group-left">
<div class="content-block div-1">1 is a happy one
</div>
<div class="content-block div-2">
2 here
</div>
</div>
<div class="group-right">
<div class="content-block div-3">
3 is not sad
</div>
</div>
</div>
<div class="parent">
<div class="group-left">
<div class="content-block">1 is a happy one
</div>
<div class="content-block forced-height">
2 here
</div>
</div>
<div class="group-right">
<div class="content-block">
<img class="img-force" src="" alt="no soup for you"> 3 is not sad
</div>
</div>
</div>
Inline elements can't position themselves like what you want as they're block level elements. You can use CSS grid and set div-2 to span two rows. There's a lot to grid but it's really flexible. Have a look. I've annotated the CSS so you can see how I've done it.
Some good resources on CSS tricks and here's a video by Kevin Powell that's a handy introduction.
.div-main {
border: 5px solid yellow;
padding: 15px;
/* this makes a grid layout with 2 columns and as many rows as needed. */
/* There's only 3 divs so that'll automatically give us 2 rows */
/* The grid-template-columns property is the width of each column - though there are some qualifications with this */
display: grid;
grid-template-columns: 30% 69%;
}
.div-main>div {
/* I've moved this to its own rule so you don't need to repeat yourself */
border: 1px solid black;
padding: 15px;
}
.div-1 {
/* I've kept the height of your original divs */
height: 30vh;
}
.div-2 {
height: 50vh;
/* setting grid-row: span 2 makes this div use two rows when it's being displayed */
/* this allows the third div to appear to the left */
/* in effect there's 4 cells in this grid but the last, bottom right cell is taken up by div-2 as we've told it to span 2 rows */
grid-row: span 2;
}
.div-3 {
height: 30vh;
}
<div class="div-main">
<div class="div-1">
1
</div>
<div class="div-2">
2
</div>
<div class="div-3">
3
</div>
</div>
I tried to achieve the masonry style using css with the column layout like the markup below.
I want to know if it's possible to make the .green one to take two columns instead of one?
Thank you in advance!
.parent{
column-gap: 1rem;
column-count: 2;
}
.element{
display:inline-block;
background:red;
width:100%;
height:100px;
}
.green{
background:green;
}
<div class="parent">
<div class="element green">
</div>
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
With CSS grid you can use grid-column: span 2:
.wrapper {
display: grid;
grid-gap: 0.5rem;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-flow: dense;
padding: 0.5rem;
}
.box {
background-color: lightblue;
padding: 0.5rem;
}
.a,
.d,
.e,
.f {
background-color: lightcoral;
grid-column: span 2; /* <-- here is the trick */
}
<div class="wrapper">
<div class="box a">A</div>
<div class="box b">B</div>
<div class="box c">C</div>
<div class="box d">D</div>
<div class="box e">E</div>
<div class="box f">F</div>
<div class="box g">G</div>
<div class="box h">H</div>
</div>
Learn more about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column
Regarding masonry style: At the time of writing, Level 3 of the CSS Grid Layout specification includes a masonry value for grid-template-columns and grid-template-rows layout, though browser support is pretty non-existent: https://caniuse.com/?search=masonry
Learn about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Masonry_Layout
So instead I used grid-auto-flow: dense; on the grid, which makes grid item G come before grid item F. It's not really masonry style (placing elements in optimal position based on available vertical space), but it comes close by making the grid dense filling up all available horizontal space with the next grid item that fits that space.
"dense" packing algorithm attempts to fill in holes earlier in the grid
Learn about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow
Oh, if you are new to CSS grid, I recommend watching Wes Bos' talk “CSS Grid in 45 Minutes!”: https://www.youtube.com/watch?v=DCZdCKjnBCs
CSS Grid layout provides a simple, easy and efficient solution.
.parent {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 100px;
grid-gap: 1rem;
}
.element.green {
grid-column: 1 / -1;
background: green;
}
.element {
background: red;
}
<div class="parent">
<div class="element green"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
More information:
Make a grid column span the entire row
CSS-only masonry layout
I would say, no you can't make the single .green element take up two columns, becuase you are specifically telling the browser to use two columns. If you need it to span the two columns, then I would suggest using a separate element. Perhaps a more suitable solution for this would be to use the CSS grid layout. The snippet below contains an example of both of these solutions:
.parent {
column-gap: 1rem;
column-count: 2;
}
.element {
display: inline-block;
background: red;
width: 100%;
height: 100px;
}
.green {
background: green;
width: 100%;
height: 100px;
margin-bottom: 1rem;
}
.grid-container {
margin-top: 20px;
display: grid;
grid-template-columns: auto auto;
grid-gap: 1rem;
}
.greenGrid {
background: green;
height: 100px;
grid-column-start: 1;
grid-column-end: 3;
}
.redGrid {
background: red;
height: 100px;
}
<div class="green">
</div>
<div class="parent">
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
<div class='grid-container'>
<div class='greenGrid'></div>
<div class='redGrid'></div>
<div class='redGrid'></div>
<div class='redGrid'></div>
</div>
I am trying to create a disk utilization chart React component, where I need different colored boxes of various sizes based on the percentage.
How do I do this in CSS & HTML? What is the best way to have these boxes sized based on a percentage?
https://codepen.io/blitzkriegz/pen/Gzgpzb
<div class="wrapper">
<div class="box i">
<div class="box j">20% Item 1</div>
<div class="box k">30% Item 2</div>
<div class="box l">40% Free</div>
</div>
</div>
CSS:
body {
margin: 5px
}
.box {
background-color: gray;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
.box .box {
margin: 10px;
background-color: darkblue;
}
.j {
margin: 10px;
background-color: green;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 2fr 1fr 1fr 2fr 1fr;
background-color: #fff;
color: #444;
}
.i {
padding: 0;
grid-gap: 2px;
grid-column: auto / span 3;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
Consider using flex-box for this, rather than grid.
Flex box gives you an easy and convenient means of achieving what you want here; to control and set variable percentage based widths of box elements in a horizontal arrangement (along the "row" axis) without the need for the clearfix trick.
One approach might be as follows:
body {
margin: 5px
}
.box {
margin: 10px;
background-color: darkblue;
}
.j {
background-color: green;
/* Set percentage explicitly */
width:20%;
}
.k {
/* Set percentage explicitly */
width:30%;
}
.l {
/* Set percentage explicitly */
width:40%;
}
.wrapper {
padding: 0;
background-color: gray;
color: #fff;
border-radius: 5px;
font-size: 150%;
/* Add this to use flex-box */
display:flex;
flex-direction:row;
}
<!-- simplifiy you markup -->
<div class="wrapper">
<div class="box j">20% Item 1</div>
<div class="box k">30% Item 2</div>
<div class="box l">40% Free</div>
</div>
If you're using ReactJS to render the markup via JSX (I noticed reactjs is tagged in your OP), you can use this approach to set the widths of boxes dynamically via inline styling:
<div className="wrapper">
<div className="box j" style={{ width : '20%' }}>20% Item 1</div>
<div className="box k" style={{ width : '30%' }}>30% Item 2</div>
<div className="box l" style={{ width : '40%' }}>40% Free</div>
</div>
Hope that helps!