I want to be able to reverse the order of columns (the 2 small to the left, the big one right). I've tried several solutions but didn't find one that works.
Here's the code:
.images-block-box{
display: grid;
grid-gap: 16px;
grid-template-columns: 708fr 340fr;
& > div:first-child{
grid-row: span 2;
}
&.reverse{
grid-template-columns: 340fr 708fr;
& > div:first-child{
order: 2; // doesn't work (I want to place the first item at the end of the 3)
}
}// reverse
}// images-block-box
Note that I really want to reverse the order of the columns themselves, not just their dimensions.
Simply adjust grid-column and conisder grid-auto-flow:dense; to allow the next elements to be placed before:
.grid {
display: grid;
grid-gap: 16px;
grid-template-columns: 2fr 1fr;
grid-auto-flow:dense;
margin:5px;
}
.grid div {
min-height: 50px;
border: 1px solid;
}
.grid div:first-child {
grid-row: span 2;
}
.grid.reverse {
grid-template-columns: 1fr 2fr;
}
.grid.reverse div:first-child {
grid-column:2;
}
<div class="grid">
<div></div>
<div></div>
<div></div>
</div>
<div class="grid reverse">
<div></div>
<div></div>
<div></div>
</div>
dense
If specified, the auto-placement algorithm uses a “dense” packing algorithm, which attempts to fill in holes earlier in the grid if smaller items come up later. This may cause items to appear out-of-order, when doing so would fill in holes left by larger items.ref
Another option is to place the big box to the last column by using grid-column-end: -1 - see demo below:
.images-block-box {
display: grid;
grid-gap: 16px;
grid-template-columns: 708fr 340fr;
grid-template-rows: 100px 100px;
grid-auto-flow: column;
}
.images-block-box>div {
border: 1px solid;
}
.images-block-box>div:first-child {
grid-row: span 2;
}
.images-block-box.reverse {
grid-template-columns: 340fr 708fr;
}
.images-block-box.reverse>div:first-child {
grid-column-end: -1;
}
<div class="images-block-box">
<div></div>
<div></div>
<div></div>
</div>
<br/>
<div class="images-block-box reverse">
<div></div>
<div></div>
<div></div>
</div>
grid-column-end
<integer> && <custom-ident>?
Contributes the nth grid line to the grid
item’s placement. If a negative integer is given, it instead counts in
reverse, starting from the end edge of the explicit grid.
Since there are 2 answers that could be marked as accepted (thanks to #kukkuz and #Temani Afif) I'm posting here a sum up. The working techniques pointed out till now are:
grid-auto-flow: dense (container) + grid-column: 2 (first-child)
grid-auto-flow: column (container) + grid-column-end: -1 (first-child)
The rest of the code remains the same. Please take a look at the related answers.
Both are currently working well (at least in major/modern browsers).
Then Maybe You can use a different approach
.grid {
display: grid;
grid-template-columns: 5fr 2fr;
grid-template-rows: 1fr 1fr;
height: 500px;
grid-gap: 2rem;
}
.one {
background-color: red;
grid-row: 1 / 3;
}
.two {
background-color: green;
}
.three {
background-color: blue;
}
.reverse > .one {
grid-column: 2 / 3;
grid-row: 2 / 3;
}
.reverse > .three {
grid-column: 1 / 2;
grid-row: 1 / 3;
}
<h1>Without Reverse</h1>
<div class="grid">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
<h1>With Reverse</h1>
<div class="grid reverse">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
Related
I have 4 icons which should align like the image below.
I've tried to first put them into a <div> with a class which controlls the position.
Now with my knowledge I would give every each image a absolute position, but that will not work, because on every res. my images are not together and just all over the place.
How can I align my images like a "flower" in a responsive way.
For a responsive layout you can use CSS grid:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(4, 1fr);
width: 50vw;
aspect-ratio: 3 / 2;
}
.container>div {
aspect-ratio: 1 / 1;
border: 1px solid black;
box-sizing: border-box;
}
.container>div:nth-child(1) {
grid-column: 1;
grid-row: 2 / span 2;
}
.container>div:nth-child(2) {
grid-column: 2;
grid-row: 1 / span 2;
}
.container>div:nth-child(3) {
grid-column: 3;
grid-row: 2 / span 2;
}
.container>div:nth-child(4) {
grid-column: 2;
grid-row: 3 / span 2;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Obviously set the container width to what you require.
This snippet sets the divs in a clockwise fashion starting at the left most div.
I have just recreated what you posted above. I can help you when you specify what you really need
.main {
display: flex;
height:100%;
align-items:center
}
.sec{
height: 50px;
width: 50px;
border:1px solid black
}
<div class="main">
<div class="sec"></div>
<div class="sec2">
<div class="sec"></div>
<div class="sec"></div>
</div>
<div class="sec"></div>
</div>
Need to create 3 columns wrapped in a flex container and aligned vertically
.wrapper {
display: flex;
}
.column {
align-items: center;
}
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;
(I am trying to convert this data entry page from a very primitive CSS/HTML "table" layout to something a bit better, using CSS Grid layout).
In line with common practice, it seems, I've made it 12 columns wide. Each entry field has a label, of the same width. In other words my CSS is currently very repetitive:
.container {
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
grid-gap: 10px;
}
#SigNameLabel {
grid-column: 1 / 13;
grid-row: 2;
}
#SignatureName {
grid-column: 5 / 13;
grid-row: 2;
}
#PaymentNoLabel {
grid-column: 1 / 13;
grid-row: 3;
}
#PaymentNo {
grid-column: 5 / 13;
grid-row: 3;
}
#CurrencyLabel {
grid-column: 1 / 13;
grid-row: 4;
}
#Currency {
grid-column: 5 / 13;
grid-row: 4;
}
* {
border: 1px solid #999;
}
<div class="container">
<div id='SigNameLabel' class='unselectable'>Signature name:</div>
<div id='SignatureName' class='unselectable dataField single-line'></div>
<div id='PaymentNoLabel' class='unselectable'>Payment No:</div>
<div id='PaymentNo' class='unselectable dataField single-line'></div>
<div id='CurrencyLabel' class='unselectable'>Currency:</div>
<div id='Currency' class='dataField single-line'></div>
</div>
Short of using JS to "create" the layout in automated fashion, i.e. by analysing the DIVs in the container, is there any way to make the CSS less cumbersome and explicit, more just "taking its lead from" what the HTML does?
For example, I have had to give a specific ID to each of the labels here: when they each sat in their own TD they didn't need that. Is there any way each such label DIV could be given a class, say left-hand-column, and somehow they could all have grid-column: 1 / 13 applied to them, and somehow the same grid-row as the data field DIV to their right?
You can simplify your code like below. And you don't necessarily need 12 columns
.container {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-gap: 10px;
}
.container>*:nth-child(even) {
grid-column: span 2;
border:1px solid;
}
.container>*:nth-child(odd) {
/* Not sure if you need this but it will allow
the full width of the grid like your code grid-column: 1 / 13;
width:calc(300% + 2*10px); */
border:1px solid red;
}
<div class="container">
<div id='SigNameLabel' class='unselectable'>Signature name:</div>
<div id='SignatureName' class='unselectable dataField single-line'></div>
<div id='PaymentNoLabel' class='unselectable'>Payment No:</div>
<div id='PaymentNo' class='unselectable dataField single-line'></div>
<div id='CurrencyLabel' class='unselectable'>Currency:</div>
<div id='Currency' class='dataField single-line'></div>
</div>
I have a card built with CSS Grid layout. There might be an image to the left, some text to the right top and maybe a button or a link at the right bottom.
In the code below, how can I make the green area take up as much space as possible and at the same time make the blue area take up as little space as possible?
The green should push the blue area down as far as possible.
https://jsfiddle.net/9nxpvs5m/
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-areas:
"one two"
"one three"
}
.one {
background: red;
grid-area: one;
padding: 50px 0;
}
.two {
background: green;
grid-area: two;
}
.three {
background: blue;
grid-area: three;
}
<div class="grid">
<div class="one">
One
</div>
<div class="two">
Two
</div>
<div class="three">
Three
</div>
</div>
Adding grid-template-rows: 1fr min-content; to your .grid will get you exactly what you're after :).
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: 1fr min-content;
grid-template-areas:
"one two"
"one three"
}
.one {
background: red;
grid-area: one;
padding: 50px 0;
}
.two {
background: green;
grid-area: two;
}
.three {
background: blue;
grid-area: three;
}
<div class="grid">
<div class="one">
One
</div>
<div class="two">
Two
</div>
<div class="three">
Three
</div>
</div>
Jens edits: For better browser support this can be used instead: grid-template-rows: 1fr auto;, at least in this exact case.
A grid is a series of intersecting rows and columns.
You want the two items in the second column to automatically adjust their row height based on their content height.
That's not how a grid works. Such changes to the row height in the second column would also affect the first column.
If you must use CSS Grid, then what I would do is give the container, let's say, 12 rows, then have items span rows as necessary.
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: repeat(12, 15px);
}
.one {
grid-row: 1 / -1;
background: red;
}
.two {
grid-row: span 10;
background: lightgreen;
}
.three {
grid-row: span 2;
background: aqua;
}
.grid > div {
display: flex;
align-items: center;
justify-content: center;
}
<div class="grid">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
</div>
Otherwise, you can try a flexbox solution.
.grid {
display: flex;
flex-flow: column wrap;
height: 200px;
}
.one {
flex: 0 0 100%;
width: 30%;
background: red;
}
.two {
flex: 1 0 1px;
width: 70%;
background: lightgreen;
}
.three {
background: aqua;
}
.grid>div {
display: flex;
align-items: center;
justify-content: center;
}
<div class="grid">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
</div>
When using grid, and you have grid template area used, and by chance you gave a particular area a width, you are left with a space grid does automatically.
In this situation, let grid-template-columns be either min-content or max-content, so that it adjusts its position automatically.
A possible approach might be grouping two and three together, and using flexbox:
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-areas: "one two"
}
.one {
background: red;
grid-area: one;
padding: 50px 0;
}
.wrap {
grid-area: two;
display: flex;
flex-direction: column;
}
.two {
background: green;
flex: 1;
}
.three {
background: blue;
}
<div class="grid">
<div class="one">
One
</div>
<div class="wrap">
<div class="two">
Two
</div>
<div class="three">
Three
</div>
</div>
</div>
Definitely not the most elegant solution and probably not best practice, but you could always add more lines of
"one two"
before the part where you have
"one three"
so it ends up looking like
.grid {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-areas:
"one two"
"one two"
"one two"
"one three"
}
Again, pretty sure this is just a work around and there's better solutions out there... But this does work, to be fair.
Just use width: 100% and height: 100% in the CSS class of the item you want to fill the grid. Join a max-width property and a max-height property if you don't want a grid item inside a grid container to grow more than some size.
I was hoping to use CSS Grid to reverse the apparent order of two side-by-side divs, where one of the divs grows arbitrarily (I don't want to use floats).
I've created a plunkr here: http://plnkr.co/edit/6WZBnHbwhD7Sjx2ovCO7?p=preview
#container {
grid-template-columns: 240px 1fr;
display: grid;
}
.a {
background: yellow;
}
.b {
background: blue;
color: white;
}
#container>.a {
grid-column: 1;
}
#container>.b {
grid-column: 2;
}
#container.reverse>.a {
grid-column: 2;
}
#container.reverse>.b {
grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
The crux of it is that when I have the .reverse class applied (so that you should see B | A), B is offset to a new line so it looks more like:
| A
B
If I invert the document ordering of .a with .b, this goes back to normal (but of course, if I drop the .reverse class, I get the same problem).
Why is this, and how can I address?
As the Grid auto-placement algorithm lays out items in the container, it uses next available empty cells (source).
In your source code the A element comes before the B element:
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
Therefore, the grid container first places A, then uses the next available space to place B.
By default, the auto-placement algorithm looks linearly through the grid without backtracking; if it has to skip some empty spaces to place a larger item, it will not return to fill those spaces. To change this behavior, specify the dense keyword in grid-auto-flow.
http://www.w3.org/TR/css3-grid-layout/#common-uses-auto-placement
grid-auto-flow: dense
One solution to this problem (as you have noted) is to override the default grid-auto-flow: row with grid-auto-flow: dense.
With grid-auto-flow: dense, the Grid auto-placement algorithm will look to back-fill unoccupied cells with items that fit.
#container {
display: grid;
grid-template-columns: 240px 1fr;
grid-auto-flow: dense; /* NEW */
}
7.7. Automatic Placement: the grid-auto-flow
property
Grid items that aren’t explicitly placed are automatically placed into
an unoccupied space in the grid container by the auto-placement
algorithm.
grid-auto-flow controls how the auto-placement algorithm works,
specifying exactly how auto-placed items get flowed into the grid.
dense
If specified, the auto-placement algorithm uses a “dense” packing
algorithm, which attempts to fill in holes earlier in the grid if
smaller items come up later. This may cause items to appear
out-of-order, when doing so would fill in holes left by larger items.
#container {
display: grid;
grid-template-columns: 240px 1fr;
grid-auto-flow: dense; /* NEW */
}
.a {
background: yellow;
}
.b {
background: blue;
color: white;
}
#container>.a {
grid-column: 1;
}
#container>.b {
grid-column: 2;
}
#container.reverse>.a {
grid-column: 2;
}
#container.reverse>.b {
grid-row: 1;
grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
grid-row: 1
Another solution would be to simply define the row for the second item.
#container>.b {
grid-column: 2;
grid-row: 1; /* NEW */
}
#container {
display: grid;
grid-template-columns: 240px 1fr;
}
.a {
background: yellow;
}
.b {
background: blue;
color: white;
}
#container>.a {
grid-column: 1;
}
#container>.b {
grid-column: 2;
grid-row: 1; /* NEW */
}
#container.reverse>.a {
grid-column: 2;
}
#container.reverse>.b {
grid-row: 1;
grid-column: 1;
}
<div id="container" class="reverse" style="width: 800px;">
<div class="a">A</div>
<div class="b">B</div>
</div>
The simplest way is to add order: 1 to element B or order: -1 to element A in .reverse
It's also correct CSS rather than hack-y
I'm not sure how to reverse more grid items. But if you have 2 grid items in your grid, you can simply position 2nd grid item using below code.
#container > .b {
grid-column-start: 1;
grid-row-start: 1;
}
I had this same issue just now. I tried auto-row-dense and then set the direction of the container parent to rtl. It worked.
Just this, on the plunker link, seemed to do the trick.
.reverse{
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-flow: dense;
direction: rtl;
}
You can use direction property to reverse a grid x-axis order.
Nested elements will be reversed too so you have to make sure to add additional styles to fix this behavior.
<div class="grid">
<div class="grid-item"><div>
</div>
<style>
.grid { direction : rtl; }
.grid-item { direction : ltr; }
</style>
Edit: this may work but could cause accessibilty issues.
Round peg in square hole
Remember even if you're using fancy 'new' grid features the older flex layout will still work. You can combine them, nest them and sometime you have to admit that certain problems like this may just be better solved with good old
flex-direction: row-reverse
But I know some people will want to downvote me for that so here's another way with grid.
Use named template regions
You can use named template regions and reverse them in the definition.
#container
{
grid-template-areas: a b;
grid-template-rows: 240px 1fr;
display: grid;
}
#container.reverse
{
// note the order is flipped for both these properties
grid-template-areas: b a;
grid-template-rows: 1fr 240px;
}
.a {
grid-area: a;
background: yellow;
}
.b {
grid-area: b;
background: blue;
color: white;
}
Here's an more complex example that uses that technique with media queries
I found out: I need to apply grid-auto-flow: dense; on the container:
#container {
grid-template-columns: 240px 1fr;
display: grid;
grid-auto-flow: dense;
}
According to MDN, this algorithm attempts to fill in holes earlier in the grid.
I want to mention a solution which is also relevant to this question in some cases. When having a multi-row layout, and you want a reversed look of how you grid fills up.
You can play with grid-start combined with some :nth-child & :last-child selectors to achieve a reverse auto flow.
Reversed grid-auto-flow: column
.container{
display: grid;
width: 10rem;
gap: 0.5rem;
grid-template-rows: repeat(2, 1fr);
grid-auto-flow: column; /* => vertical grid*/
}
/* REMOVE THIS TO SEE THE DIFFERENCE */
.pixel:nth-child(odd):last-child { /* reversed auto-flow: column */
grid-row-start: 2;
}
.pixel{
width: 2rem;
height: 2rem;
background: red;
border: 1px solid black
}
<div class="container">
<!-- ADD/REMOVE SOME PIXELS to see the result -->
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
<div class="pixel"></div>
</div>
Reversed: horizontal & vertical
.container{
display: grid;
width: 10rem;
gap: 0.5rem;
grid-template-rows: repeat(2, 1fr);
grid-auto-flow: column;
direction: rtl; /* reversed horizontal */
}
/* REMOVE THIS TO SEE THE DIFFERENCE */
.pixel:nth-child(odd):last-child { /* reversed vertical */
grid-row-start: 2;
}
.pixel{
width: 2rem;
height: 2rem;
background: red;
border: 1px solid black
}
<div class="container">
<!-- ADD/REMOVE SOME PIXELS to see the result -->
<div class="pixel">1</div>
<div class="pixel">2</div>
<div class="pixel">3</div>
<div class="pixel">4</div>
<div class="pixel">5</div>
<div class="pixel">6</div>
<div class="pixel">7</div>
</div>
I found out: I need to apply grid-auto-flow: dense; on the container: