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/
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>
Below image has been created by the graphics editor. The target is get the same view by CSS grid.
Currently, the middle row fills the viewport's width:
html, body {
height: 100%;
}
.TwoColumnsLayout {
display: grid;
grid-template-areas:
"UPPER_FIXED_CONTENT UPPER_FIXED_CONTENT"
"SIDEBAR SPECIFIC_CONTENT"
"BOTTOM_FIXED_CONTENT BOTTOM_FIXED_CONTENT";
grid-template-columns: 100px 1fr;
grid-template-rows: auto 1fr auto;
height: 100%;
}
.TwoColumnsLayout-UpperFixedContent {
height: 30px;
grid-area: UPPER_FIXED_CONTENT;
background-color: lightpink;
}
.TwoColumnsLayout-Sidebar {
overflow-y: auto;
grid-area: SIDEBAR;
background-color: gold;
width: 100px;
}
.TwoColumnsLayout-SpecificContent {
overflow-y: auto;
grid-area: SPECIFIC_CONTENT;
background-color: aquamarine;
}
.TwoColumnsLayout-BottomFixedContent {
height: 30px;
grid-area: BOTTOM_FIXED_CONTENT;
background: deepskyblue;
}
<div class="TwoColumnsLayout">
<div class="TwoColumnsLayout-UpperFixedContent"></div>
<div class="TwoColumnsLayout-Sidebar"></div>
<main class="TwoColumnsLayout-SpecificContent"></main>
<div class="TwoColumnsLayout-BottomFixedContent"></div>
</div>
In this case, justify-content: center; will change nothing.
If to apply justify-items: center; to grid container and also justify-self: stretch; to first and last element, we'll get:
html, body {
height: 100%;
}
.TwoColumnsLayout {
display: grid;
grid-template-areas:
"UPPER_FIXED_CONTENT UPPER_FIXED_CONTENT"
"SIDEBAR SPECIFIC_CONTENT"
"BOTTOM_FIXED_CONTENT BOTTOM_FIXED_CONTENT";
grid-template-columns: 100px 1fr;
grid-template-rows: auto 1fr auto;
justify-items: center;
height: 100%;
}
.TwoColumnsLayout-UpperFixedContent {
height: 30px;
grid-area: UPPER_FIXED_CONTENT;
background-color: lightpink;
justify-self: stretch;
}
.TwoColumnsLayout-Sidebar {
overflow-y: auto;
grid-area: SIDEBAR;
background-color: gold;
width: 100px;
}
.TwoColumnsLayout-SpecificContent {
overflow-y: auto;
grid-area: SPECIFIC_CONTENT;
background-color: aquamarine;
}
.TwoColumnsLayout-BottomFixedContent {
height: 30px;
grid-area: BOTTOM_FIXED_CONTENT;
background: deepskyblue;
justify-self: stretch;
}
<div class="TwoColumnsLayout">
<div class="TwoColumnsLayout-UpperFixedContent"></div>
<div class="TwoColumnsLayout-Sidebar"></div>
<main class="TwoColumnsLayout-SpecificContent"></main>
<div class="TwoColumnsLayout-BottomFixedContent"></div>
</div>
I expected it will be simple with CSS grid...
It there the solutions without adding of extra HTML elements?
You can do it like below. The 600px will simulate the max-width which is the area for the sidebar and content
body {
margin:0;
}
.TwoColumnsLayout {
--max: 600px; /* your max-width */
min-height: 100vh;
display: grid;
grid-template-columns:
calc((100% - var(--max))/2) 100px 1fr calc((100% - var(--max))/2);
grid-template-rows: auto 1fr auto;
}
.TwoColumnsLayout-UpperFixedContent,
.TwoColumnsLayout-BottomFixedContent{
height: 30px;
grid-column:1/-1;
background-color: lightpink;
}
.TwoColumnsLayout-Sidebar {
overflow-y: auto;
grid-column: 2;
background-color: gold;
}
.TwoColumnsLayout-SpecificContent {
overflow-y: auto;
background-color: aquamarine;
}
.TwoColumnsLayout-BottomFixedContent {
background: deepskyblue;
}
<div class="TwoColumnsLayout">
<div class="TwoColumnsLayout-UpperFixedContent"></div>
<div class="TwoColumnsLayout-Sidebar"></div>
<main class="TwoColumnsLayout-SpecificContent"></main>
<div class="TwoColumnsLayout-BottomFixedContent"></div>
</div>
<div class='container'>
<div class='col-1'></div>
<div class='col-2'></div>
</div>
.container{
width: 100vw;
height: 100vh;
display: flex;
}
.col-1{
width: 40%;
height: 100%;
background-color: blue;
}
.col-2{
width: 60%;
height: 100%;
background-color: red;
}
How can I achieve the result of col-1 adjusting its width up until a certain point? (let's say its width will stop shrinking at 20 rem, and col-2's width will auto adjust to fill the remaining width of the container space available?
Start ditching flex in favor of grid, it's so much easier and more powerful as well:
body { margin: 0; }
.container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: minmax(15rem, 1fr) 1fr;
}
.col-1 {
background-color: blue;
}
.col-2 {
background-color: red;
}
<div class='container'>
<div class='col-1'></div>
<div class='col-2'></div>
</div>
you can use display: grid; instead of flex. then set grid-template-columns: 20rem 1fr; and then set both col-1 and col-2 width to 100%. that if you change the grid-template-columns both col-1 and col-2 will adjust with it!
i think this should work!
.container{
width: 100vw;
height: 100vh;
display: flex;
}
.col-1{
width: 20%;
height: 100%;
background-color: blue;
}
.col-2{
width: calc(100% - 100px);
height: 100%;
background-color: red;
}
<div class='container'>
<div class='col-1'></div>
<div class='col-2'></div>
</div>
by replacing width: 60% from .col-2 to width: calc(100% - 100px); using calc!
If you're using display: flex you should use the flex methods of defining the scaling (instead of width).
.container {
width: 100vw;
height: 100vh;
display: flex;
flex-flow: row nowrap;
}
.col-1 {
flex: 0 1 20rem;
background-color: blue;
}
.col-2 {
flex: 1 0 0;
background-color: red;
}
<div class='container'>
<div class='col-1'></div>
<div class='col-2'></div>
</div>
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: __}
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