I have a page designed like this:
main {
display: flex;
}
div {
width: 50px;
height: 50px;
margin: 2px;
text-align: center;
}
.div1 {
background-color: green;
}
.div2 {
background-color: red;
}
<main>
<section>
<div class="div1">A</div>
<div class="div1">B</div>
<div class="div1">C</div>
</section>
<section>
<div class="div2">D</div>
<div class="div2">E</div>
<div class="div2">F</div>
</section>
</main>
I am applying responsiveness. I would like to know if it is possible to use only css to organize the divs this:
The only way I see to achieve the layout with a <section> tag present separating each div1 and div2 would be to use positioning each child elements left and top positions relative to the parent. It is very static and likely has a high potential of breaking with content and scrolling, etc...
Not recommended... see the hidden snippit below to see that working
.main section {
position: relative;
}
.one {
position: absolute;
left: 0;
top: 0;
}
.four {
position: absolute;
left: 55px;
top: 0;
}
.two {
position: absolute;
left: 0;
top: 55px;
}
.three {
position: absolute;
left: 55px;
top: 55px;
}
.five {
position: absolute;
left: 0;
top: 110px;
width: 210%;
overflow: auto;
}
.six {
position: absolute;
left: 0;
top: 165px;
width: 210%;
overflow: auto;
}
div {
width: 50px;
height: 50px;
margin: 2px;
text-align: center;
}
.div1 {
background-color: green;
}
.div2 {
background-color: red;
}
<div class="main">
<section>
<div class="div1 one">1</div>
<div class="div1 two">2</div>
<div class="div1 three">3</div>
</section>
<section>
<div class="div2 four">4</div>
<div class="div2 five">5</div>
<div class="div2 six">6</div>
</section>
</div>
A more cohesive approach would be to get rid of the <section> tags and use a grid layout...
You still have the classes div1 and div2 for alternate styling. Using the grid layout you can create a grid-template-area using the grid-area on individual class names for each element.
While you still have your child elements laid out incrementally one, two, three, four, etc... You can move a child element anywhere in the grid pattern using the grid-template-area calling on the elements grid-area value.
In the following example, each div has a class representing its position in the original layout, one, two, three, etc...
Note the column and row fr units... very literal in its approach. Visualize two columns each separated equally per column, then four rows, each separated equally per row, then we add the elements with the grid-template-area...
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
grid-template-area:
"one four"
"two three"
"five five"
"six six";
}
html {
--width: 100%;
--height: 100%;
}
#main {
display: flex;
justify-content: center;
}
div {
display: flex;
align-items: center;
justify-content: center;
}
.grid-container {
height: 400px;
width: 200px;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
grid-gap: 2px 2px;
grid-template-areas: "one four" "two three" "five five" "six six";
}
.one {
grid-area: one;
width: var(--width);
height: var(--height);
}
.two {
grid-area: two;
width: var(--width);
height: var(--height);
}
.three {
grid-area: three;
width: var(--width);
height: var(--height);
}
.four {
grid-area: four;
width: var(--width);
height: var(--height);
}
.five {
grid-area: five;
width: var(--width);
height: var(--height);
}
.six {
grid-area: six;
width: var(--width);
height: var(--height);
}
.div1 {
background-color: green;
}
.div2 {
background-color: red;
}
<div id="main">
<div class="grid-container">
<div class="div1 one box">A</div>
<div class="div1 two box">B</div>
<div class="div1 three box">C</div>
<div class="div2 four box">D</div>
<div class="div2 five box">E</div>
<div class="div2 six box">F</div>
</div>
</div>
yes you could by using orders like this .div1 {order: __}
Related
I got 2 columns grid with following layout:
My issue is that when I use images inside the right column (1 image inside each box)..Images overflow and whole grid kind of acts weird.
It looks something like this:
Codepen Link: https://codepen.io/kazmi066/pen/MWXGgaL?editors=1100
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.grid {
background: green;
width: 100%;
max-height: 70vh;
display: grid;
gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
}
.col1 {
height: 100%;
background: red;
}
.col2 {
height: 100%;
background: orange;
}
.box1 {
width: 100%;
height: 50%;
border: 1px solid black;
}
.box2 {
width: 100%;
height: 50%;
border: 1px solid blue;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="grid">
<div class="col1"></div>
<div class="col2">
<div class="box1"><img src="https://images.unsplash.com/photo-1600585154340-be6161a56a0c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8N3x8fGVufDB8fHx8&w=1000&q=80" alt="property"/></div>
<div class="box2"><img src="https://images.unsplash.com/photo-1600585154340-be6161a56a0c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8N3x8fGVufDB8fHx8&w=1000&q=80" alt="property" /></div>
</div>
</div>
I want the images to adjust inside the boxes perfectly without the need of custom height and width so that any size of image can work in this scenario.
fit would be object-fit: contain; for the image not cover.
but if the ratio of the image is not the ratio of the box, you'll have blank
you can put the image in background of box1, box2... with a background size cover. It will cover entirely and clipped the overflow. If box ratio "totally" different of the image, lot of image can be clipped, but it's not so often.
I've found a way, only CSS, nothing is changed in your HTML
2 points:
1- it's using clip-path
2- image fill box space, but are clipped otherwise blank space
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.grid {
background: green;
width: 100%;
max-height: 70vh;
display: grid;
gap: 2vh;
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
grid-template-rows: 100%;
}
.col1 {
background: red;
}
.col2 {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 34vh 34vh;
background: orange;
justify-content: center;
}
.box1 {
width: 100%;
border: 1px solid black;
clip-path: inset(0);
}
.box2 {
width: 100%;
border: 1px solid blue;
clip-path: inset(0);
}
img {
width: 100%;
object-fit: contain;
}
<div class="grid">
<div class="col1"></div>
<div class="col2">
<div class="box1"><img src="https://images.unsplash.com/photo-1600585154340-be6161a56a0c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8N3x8fGVufDB8fHx8&w=1000&q=80" alt="property" /></div>
<div class="box2"><img src="https://images.unsplash.com/photo-1600585154340-be6161a56a0c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8N3x8fGVufDB8fHx8&w=1000&q=80" alt="property" /></div>
</div>
</div>
based on your grid max-height in vh, I defined all others same kind of values in vh. Lot more consistent and avoid some little strange pixels or lines here or there depending of window size.
I put a nested grid inside col2 where box1 box2 go. box have a clip-path with inset 0, meaning clipping everything out.
The solution that worked for me:
I used grid-auto-rows to create 2 rows with specific height.
Then added span to adjust the column accordingly to cover both rows.
.grid {
width: 100%;
border: 1px solid red;
display: grid;
gap: 14px;
grid-template-columns: repeat(12, 1fr);
grid-auto-rows: 280px 280px;
}
.col1 {
height: 100%;
grid-column: 1/8;
grid-row: span 2;
background: red;
}
.col2 {
grid-column: 8/13;
height: 100%;
background: orange;
}
.col2 img:first-child {
margin-bottom: 11px;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
#media (max-width: 768px) {
.grid {
grid-auto-rows: 220px 120px;
}
.col1 {
grid-column: 1/13;
}
.col2 {
grid-column: 1/13;
grid-row: span 2;
}
}
<div class="grid">
<div class="col1">
<img src="https://images.unsplash.com/photo-1600585154340-be6161a56a0c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8N3x8fGVufDB8fHx8&w=1000&q=80" alt="property"/>
</div>
<div class="col2">
<img src="https://images.unsplash.com/photo-1564013799919-ab600027ffc6?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8YmVhdXRpZnVsJTIwaG91c2V8ZW58MHx8MHx8&w=1000&q=80" alt="property"/>
<img src="https://images.pexels.com/photos/186077/pexels-photo-186077.jpeg?cs=srgb&dl=pexels-binyamin-mellish-186077.jpg&fm=jpg" alt="property" />
</div>
</div>
Final output now:
Solution-2: Found Another better solution with Grid-template-areas I guess which looks more cleaner:
.grid {
width: 100%;
border: 1px solid red;
display: grid;
gap: 14px;
grid-template-areas:
"mainImage mainImage otherImage1"
"mainImage mainImage otherImage1"
"mainImage mainImage otherImage2"
"mainImage mainImage otherImage2"
}
.mainImage {
grid-area: mainImage;
}
.otherImage1 {
grid-area: otherImage1;
}
.otherImage2 {
grid-area: otherImage2;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="grid">
<img src="https://images.unsplash.com/photo-1600585154340-be6161a56a0c?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8N3x8fGVufDB8fHx8&w=1000&q=80" alt="property" class="mainImage" />
<img src="https://images.unsplash.com/photo-1564013799919-ab600027ffc6?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8YmVhdXRpZnVsJTIwaG91c2V8ZW58MHx8MHx8&w=1000&q=80" alt="property" class="otherImage1" /> <img src="https://images.pexels.com/photos/186077/pexels-photo-186077.jpeg?cs=srgb&dl=pexels-binyamin-mellish-186077.jpg&fm=jpg" alt="property" class="otherImage2" />
</div>
<h1>something else here</h1>
I have a grid (containers) to display a navbar, a main-container and a footer. In the main-container, it is also a grid to display 3 children elements in a custom disposition using grid-area. Everything works properly.
Now, I would like to display an overlay div (overlay) which has to fit the whole main-container. To do so, I just add an additional div in the main-container with the property height: 100%; width: 100%; and play with the position property without success. Indeed, position: absolute or position: fixed make it too big and I don't want to set a fixed width or height since the layout can be responsive. And with position: relative, it is not working neither.
Do you have any idea, how I could make the overlay display above the main-container while keeping the properties width: 100%; height: 100%;?
#containers {
display: grid;
grid-template-areas: "navbar main" "navbar footer";
grid-template-rows: calc(100% - 32px) 32px;
grid-template-columns: 56px calc(100% - 56px);
}
#navbar-container {
grid-area: navbar;
background-color: blue;
}
#main-container {
grid-area: main;
height: 100%;
width: 100%;
display: grid;
grid-template-areas:
'child1 child2'
'child1 child3';
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
#footer-container {
grid-area: footer;
background-color: black;
}
#child1,
#child2,
#child3 {
padding: 10px;
}
#child1 {
grid-area: child1;
background-color: red;
}
#child2 {
grid-area: child2;
background-color: purple;
}
#child3 {
grid-area: child3;
background-color: pink;
}
#footer-container {
grid-area: footer;
}
.modal {
width: 100%;
height: 100%;
background-color: grey;
opacity: 0.5;
position: absolute;
}
<div id="containers">
<div id="navbar-container"></div>
<div id="main-container">
<div id="child1">
<span>CHILD 1</span>
</div>
<div id="child2">
<span>CHILD 2</span>
</div>
<div id="child3">
<span>CHILD 3</span>
</div>
<div class="modal">
MODAL
</div>
</div>
<div id="footer-container"></div>
</div>
Just needed to make the parent relative and the modal absolute.
#containers {
display: grid;
grid-template-areas: "navbar main" "navbar footer";
grid-template-rows: calc(100% - 32px) 32px;
grid-template-columns: 56px calc(100% - 56px);
}
#navbar-container {
grid-area: navbar;
background-color: blue;
}
#main-container {
grid-area: main;
height: 100%;
width: 100%;
display: grid;
grid-template-areas:
'child1 child2'
'child1 child3';
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
position: relative;
}
#footer-container {
grid-area: footer;
background-color: black;
}
#child1,
#child2,
#child3 {
padding: 10px;
}
#child1 {
grid-area: child1;
background-color: red;
}
#child2 {
grid-area: child2;
background-color: purple;
}
#child3 {
grid-area: child3;
background-color: pink;
}
#footer-container {
grid-area: footer;
}
.modal {
width: 100%;
height: 100%;
background-color: grey;
opacity: 0.5;
position: absolute;
}
<div id="containers">
<div id="navbar-container"></div>
<div id="main-container">
<div id="child1">
<span>CHILD 1</span>
</div>
<div id="child2">
<span>CHILD 2</span>
</div>
<div id="child3">
<span>CHILD 3</span>
</div>
<div class="modal">
MODAL
</div>
</div>
<div id="footer-container"></div>
</div>
I'm trying to build a grid where the first-row would have 400px and the second would be something like fit-content, since my first column is dynamically created and it can have an undertemined height.
The idea is, I have three blocks, 1 is dynamic, 2 and 3 are static, where 3 should always be below 2:
However I couldn't find a way to make the first row with a fixed value (400px) and the second auto to fit whatever height the block 1 have. If I set the first one auto and the second row 400px I get this:
.container {
display: grid;
grid-template-columns: auto auto;
grid-template-rows: auto 400px;
width: 400px;
}
.block-1 {
height: 300px;
width: 200px;
background: red;
}
.block-2 {
height: 100px;
width: 150px;
background: blue;
grid-column: 3/5;
}
.block-3 {
height: 100px;
width: 150px;
background: green;
grid-column: 3/5;
grid-row-start: 2;
}
<div class="container">
<div class="block-1"></div>
<div class="block-2"></div>
<div class="block-3"></div>
</div>
Is there a way to do that with grid? I could change the structure of the grid, the way I bult is not a must.
P.S. Changing the HTML is not an option.
Is this what you want?
.container {
display: grid;
grid-template-columns: auto auto;
grid-template-rows: auto 400px;
width: 400px;
}
.block-1 {
height: 300px;
width: 200px;
background: red;
grid-row: 1 / 3;
}
.block-2 {
height: 100px;
width: 150px;
background: blue;
}
.block-3 {
height: 100px;
width: 150px;
background: green;
grid-column: 2/3;
grid-row-start: 2;
}
<div class="container">
<div class="block-1"></div>
<div class="block-2"></div>
<div class="block-3"></div>
</div>
This seems like it will do the trick. I've used named grid-template-areas as shorthand.
.container {
display: grid;
grid-auto-columns: 1fr;
grid-auto-rows: 1fr;
grid-template-columns: 1fr 1fr;
grid-template-rows: min-content;
gap: 0px 0px;
grid-template-areas:
"block-1 block-2"
"block-1 block-3";
width: 400px;
}
.block-1 { grid-area: block-1; background-color: red; height: 300px}
.block-2 { grid-area: block-2; background-color: blue; height: 100px }
.block-3 { grid-area: block-3; background-color: green; height: 100px; }
<div class="container">
<div class="block-1"></div>
<div class="block-2"></div>
<div class="block-3"></div>
</div>
Hopefully that works out for you, but if you need to make any adjustments then I always find using a site with a visual UI for the grid really helps, e.g. https://grid.layoutit.com/
I have a problem in my project, where the size of the div varies, which shouldn't happen. I#ve put an example which shows it.
html, body, .grid-container { height: 100%; margin: 0; }
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
gap: 1px 1px;
}
._ {
display: grid;
grid-template-columns: 120px 120px;
grid-template-rows: 1fr 1fr;
gap: 1px 1px;
grid-area: 1 / 2 / 4 / 4;
}
.A { grid-area: 1 / 1 / 3 / 2;
align-self: flex-end;
border: 1px solid red;
position: relative;
}
.B { grid-area: 1 / 2 / 3 / 3;
border: 1px solid red;
position: relative;
}
.grid-container *:after {
content:attr(class);
position: absolute;
top: 0;
left: 0;
}
.circle {
width: 115px;
height: 115px;
background: red;
border-radius: 100px;
}
<div class="grid-container">
<div class="_">
<div class="A">
<div class="circle"></div>
</div>
<div class="B"></div>
</div>
</div>
If you do not pu the circle div in, A & B are the same height. But as soon as you put it into the A div, the size changes to perfectly equal the one of the circle, which I totally do not want to happen.
Since I'm building a Connect 4 game and I use the Border for the "GameField" it has to stay the same size.
I've already tried adding the parameter height: 690; to the A div (every circle is 115px->6 circles = 690) but then the align end did not work anymore. I also change between align-self: end; and align-self: flex-end; but that didn't change anything...
If what Im searching for isn't possible, I would love to know how else I can achieve a outline of a specificities set of cells in a css grid.
Thank you so much in advance for helping (or at least trying) me. <3
I didn't understand literally, but you can try and use this instead of above.
I think you can add the features you want (such as height) to this code I wrote.
.grid-container {
display: inline-table;
}
._ {
display: grid;
grid-template-columns: 120px 120px;
grid-template-rows: 1fr 1fr;
gap: 1px 1px;
grid-area: 1 / 2 / 4 / 4;
}
.grid-container *:not(.circle):after {
content: attr(class);
position: absolute;
top: 0;
left: 0;
}
._ > div {
border: 1px solid red;
align-self: end;
position: relative;
display: inline-flex;
}
.circle {
width: 115px;
height: 115px;
background: red;
border-radius: 100px;
align-self: end;
}
.B {
height: 20px;
}
.C {
height: 30px;
}
.D {
height: 40px;
}
<div class="grid-container">
<div class="_">
<div class="A">
<div class="circle"></div>
</div>
<div class="B"></div>
<div class="C"></div><div class="D"></div></div>
</div>
You don't have to use css for .A and .B, you're able to use like code above. Also I added two div to better understand
If I misunderstood, send me message back, I'll check again
I have a CSS grid container with 3 children, all with a different width. I want the 2 side children to be at the 2 sides of the container and the middle child to be at the center.
I tried setting the first one to justify-self: start, the middle one to justify-self: center;, and the last one to justify-self: end;, but it doesn't get centered, it just divides the space evenly.
.container {
display: grid;
grid-template-columns: auto auto auto;
height: 100px;
}
.first {
justify-self: start;
background-color: red;
width: 50px;
}
.middle {
justify-self: center;
background-color: green;
width: 70px;
}
.last {
justify-self: end;
background-color: blue;
width: 200px;
}
<div class="container">
<div class="first"></div>
<div class="middle">Center me</div>
<div class="last"></div>
</div>
Am I'm missing something? Is this not possible?
You could use the grid for the outer elements and center the middle one using absolute position and transforms like so:
.container {
display: grid;
grid-template-columns: auto auto;
height: 100px;
position:relative;
width:100%;
}
.first {
justify-self: start;
background-color: red;
width: 50px;
}
.middle {
background-color: green;
width: 70px;
position:absolute;
left: 50%;
transform: translateX(-50%);
height:100%;
}
.last {
justify-self: end;
background-color: blue;
width: 200px;
}
<div class="container">
<div class="first"></div>
<div class="middle">Center me</div>
<div class="last"></div>
</div>
But be aware that elements could overlap using this method.
Use 1fr instead of auto since you are explicitly defining the width of your elements
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
height: 100px;
/* The center */
padding-bottom: 5px;
background: linear-gradient(black, black) bottom center/5px 5px no-repeat;
}
.first {
justify-self: start;
background-color: red;
width: 50px;
}
.middle {
justify-self: center;
background-color: green;
width: 70px;
}
.last {
justify-self: end;
background-color: blue;
width: 200px;
}
<div class="container">
<div class="first"></div>
<div class="middle">Center me</div>
<div class="last"></div>
</div>