div positioning right under the other inline - html

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>

Related

Can I set an image as a grid item?

I have grid with 3 elements like this:
Now I want to replace blue elements with images (could be just dummy images).**
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: minmax(30em, auto);
justify-items: stretch;
align-items: stretch;
}
.grid-item-1 {
background: url("https://editzstock.com/wp-content/uploads/2022/04/broken-text-300x300.png");
background-size: cover;
overflow: hidden;
}
.grid-item-2 {}
.grid-item-3 {
grid-column: span 2;
grid-row: span 1;
}
.grid-item {
position: relative;
font-size: 25px;
padding: 20px;
padding-top: 50px;
background-color: #379AD6;
color: #222;
border: 1px solid white;
}
<div class="grid-container">
<div class="grid-item grid-item-1">
</div>
<div class="grid-item grid-item-2">
</div>
<div class="grid-item grid-item-3"></div>
</div>
Speaking just from experience over the past 7 years, images as grid / flex items often glitch in one way or another.
The glitch is almost always resolved by nesting the image in a container, making the container the grid / flex item.
Although images are valid as grid / flex items, until the various browsers make some more progress on this issue, I would suggest you use a container (thus keeping the images in a block formatting context).

Expanding a CSS grid area into another grid area when the latter is empty [duplicate]

This question already has answers here:
Expanding cells in CSS grid layout
(2 answers)
Closed 2 years ago.
I have the following simple grid setup. It works as intended in situations where there are both content and sidebar divs present, but I would however like the content area to expand to fill the area left by sidebar when a sidebar area is not present on the page. In the second grid in the example below, sidebar is not present but the content area does not expand to fill up the left over space. I would like it to do so.
/* Based on example from https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Grid_Template_Areas */
.content {
grid-area: main;
}
.sidebar {
grid-area: side;
}
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas:
"main side"
}
* {box-sizing: border-box;}
.wrapper {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
max-width: 940px;
margin: 0 auto 30px auto;
}
.wrapper > div {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
<!-- First grid - works fine -->
<div class="wrapper">
<div class="content">Content</div>
<div class="sidebar">Sidebar</div>
</div>
<!-- Second grid - content should expand to fill the area that would be used by sidebar -->
<div class="wrapper">
<div class="content">Content</div>
</div>
Perhaps this is a case where I shouldn't be using CSS grid for this, but rather floats?
If you don't have to use grid-area, flexbox gives intended result. No need to use float.
/* Based on example from https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Grid_Template_Areas */
.content {
flex-grow: 1;
}
.sidebar {
flex-grow: 1;
}
.wrapper {
display: flex;
}
* {box-sizing: border-box;}
.wrapper {
border: 2px solid #f76707;
border-radius: 5px;
background-color: #fff4e6;
max-width: 940px;
margin: 0 auto 30px auto;
}
.wrapper > div {
border: 2px solid #ffa94d;
border-radius: 5px;
background-color: #ffd8a8;
padding: 1em;
color: #d9480f;
}
<!-- First grid - works fine -->
<div class="wrapper">
<div class="content">Content</div>
<div class="sidebar">Sidebar</div>
</div>
<!-- Second grid - content should expand to fill the area that would be used by sidebar -->
<div class="wrapper">
<div class="content">Content</div>
</div>
You're wrapper contains two columns which are specified in:
grid-template-columns: 1fr 1fr;
Both columns are 1fr wide (1 fraction of a total of 2)
Deleting one of the divs inside will not expand the other since it is still 1 of two fractions wide.
Remove one of the columns in the grid will fix your issue:
grid-template-columns: 1fr;
As a sidenote, since your wrapper now only contains a single div inside it makes no sense for it to be a grid.

Make a child element take a third of the parent container (Parent is styled using grid-layout)

I'd want one child element to be 1/3 the size of its parent container and the other 2/3. The parent container is in a main container that uses grid-layout.
The parent container in question spans 2 columns of the main container it is contained in.
I've tried using margin, but it doesn't work: when I switch from a small screen to a large screen it moves to leave a gap.
<div class="main-container" style="display:grid; grid-template-columns: 1fr 2fr 1fr"> 1
<div></div>
<div class="parent-container" style="grid-column:span 2">
<div class="child-1"></div>
<div class="child-2"></div>
</div>
</div>
css code I've tried:
.child-1{
margin-left:-20%;
}
Child-1 must be 1/3 of parent-container and child-2 2/3 of parent-container
You can make use of the nested grid container. The dotted borders signify the width that the child elements take from the parent container. The solid borders are for the main container's child elements. Rest is explained in comments.
.main-container {
display: grid;
grid-template-columns: 1fr 2fr 1fr; /* 1/4th for Extra, 2/4th for Parent, 1/4th for Extra */
grid-auto-flow: column; /* Normal flow is row */
}
.parent-container {
display: grid; /* Nested Grid */
grid-template-columns: 1fr 2fr; /* 1/3rd for Child 1, 2/3rd for Child 2 of parent container*/
grid-auto-flow: column;
}
/* Extra styling for snippet, you just need the above logic */
.main-container {
font-size: 1.15em;
font-family: Sans-Serif;
}
.parent-container {
border: 2px solid black;
}
.parent-container>div {
background: #6660CE;
padding: 10px;
color: #fff;
text-align: center;
border: 2px dotted black;
}
.main-container>div {
background: #6660CE;
padding: 10px;
color: #fff;
text-align: center;
}
<div class="main-container">
<div class="extra">Extra</div>
<div class="parent-container">
<div class="child-1">Child 1 </div>
<div class="child-2">Child 2</div>
</div>
<div class="extra">Extra</div>
</div>
Simply give the parent element two columns with grid-template-columns, where the second column is twice the size of the first column (i.e. 1fr and 2fr).
This can be seen in the following:
.container {
display: grid;
grid-template-columns: 1fr 2fr;
}
.child-1 {
background: red;
}
.child-2 {
background: blue;
}
.child {
height: 50px;
}
<div class="container">
<div class="child child-1"></div>
<div class="child child-2"></div>
</div>
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.child:nth-child(1) {
grid-area: 1 / 1;
background-color: #9341aa;
}
.child:nth-child(2) {
grid-area: 2 / 1 / span 1 / span 2;
background-color: #ab41aa;
}
.child:nth-child(3) {
grid-area: 3 / 1 / span 1 / span 3;
background-color: #cab332;
}
<div class="container">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
</div>
Using calc, something like this should do the trick:
HTML:
<div class="main-container">
<div></div>
<div class="parent-container">
<div class="child-1"></div>
<div class="child-2"></div>
</div>
</div>
CSS:
.parent-container{
position: relative;
width: 100%;
height: 100%;
}
.parent-container .child-1,
.parent-container .child-2{
width: calc(100% / 3);
height: 100%;
float: left;
}

Placing items in a grid layout with arbitrary width, but defined span

I'm having difficulty finding the right technology/technique to display my layout. See picture:
Desired layout picture
This layout is similar to a calendar. An example cell is denoted in blue. The challenging part for me is a cell may have a child element that should span multiple cells/columns. The width of the calendar is full width, so each cell is of dynamic width.
I was originally using an HTML table but found that to be inflexible, so I have started using CSS Grid. With CSS Grid I still don't appear to be able to accomplish the desired layout. It looks like only direct child elements of the grid-container can be placed into the grid (in my case, these are cells). I desire the child elements of the cells to also be placed throughout the grid. This appears somewhat supported using "display: contents", but this is not support on all browsers, such as IE and Edge. I also see mention of CSS subgrid specification, but that doesn't appear to be available/supported yet.
Are there any other layout techniques or strategies which should allow for my desired layout design?
Edit: Here is a fiddle: https://jsfiddle.net/sy70c2j6/1683. I'd like some sort of styling to be able to specify that span2 and span3 span across 2 or 3 cells respectively.
// This doesn't accomplish it, but I desire something like this
.span2 {
grid-column: span 2;
}
You could kinda do this with grid-layout. You could create rows and for each row draw a line with :after pseudo-element. And you could also create columns with absolute positioned elements. Then in each row you can create cells that can span on multiple columns.
.grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
position: relative;
}
.row {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-gap: 20px;
grid-column: span 7;
position: relative;
}
.cols {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
height: 100%;
width: 100%;
display: grid;
grid-template-columns: repeat(7, 1fr);
z-index: -1;
grid-gap: 20px;
}
.cols > div {
border-left: 1px solid black;
grid-column: span;
}
.row:after {
content: '';
border-bottom: 1px solid black;
width: 100%;
position: absolute;
left: 0;
bottom: 0;
right: 0;
}
body {
padding: 0;
margin: 0;
}
.cell {
border: 1px solid #8EBA75;
background: #D5E7D3;
padding: 20px;
}
.row-1 {grid-row: 1}
.row-2 {grid-row: 2}
.row-3 {grid-row: 3}
.col-1-4 {grid-column: 1 / 4;}
.col-1-2 {grid-column: 1 / 2;}
.col-3-4 {grid-column: 3 / 4}
.col-5-7 {grid-column: 5 / 7}
.col-3-5 {grid-column: 3 / 5}
<div class="grid">
<div class="row">
<div class="cell col-1-4 row-1"></div>
<div class="cell col-1-2 row-2"></div>
</div>
<div class="row">
<div class="cell col-3-4 row-1"></div>
<div class="cell col-5-7 row-1"></div>
<div class="cell col-3-4 row-2"></div>
<div class="cell col-3-5 row-3"></div>
</div>
<div class="cols">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>

CSS - Positioning of multiple adjacent divs to have one stack on top of each other between 2 divs [duplicate]

This question already has answers here:
Make a div span two rows in a grid
(2 answers)
Closed 2 years ago.
I'm facing an issue where I need to make several adjacent div to position a certain way:
Their html layout positions are right next to each other:
<div class="parent">
<div class="div1">....</div>
<div class="div2">....</div>
<div class="div3">....</div>
<div class="div4">....</div>
</div>
I've tried with flex boxes and floating out Div1 and Div4 out but it's not working. I also need Div1 and Div4's height to all be vertically aligned to its correct dynamic height depending on the contents of Div2 and Div3.
CSS grid may help you solve it easily.
.parent {
display: grid;
grid-gap: 10px;
grid-template-columns: [col1-start] 100px [col2-start] 100px [col3-start] 100px [col3-end];
grid-template-rows: [row1-start] auto [row2-start] auto [row2-end];
}
.div1, .div2, .div3, .div4 {
background-color: #444;
color: #fff;
padding: 20px;
}
.div1 {
grid-column: col1-start;
grid-row: row1-start / row2-end ;
}
.div2 {
grid-column: col2-start ;
grid-row: row1-start;
}
.div3 {
grid-column: col2-start;
grid-row: row2-start ;
}
.div4 {
grid-column: col3-start ;
grid-row: row1-start / row2-end ;
}
<div class="parent">
<div class="div1">....</div>
<div class="div2">....</div>
<div class="div3">....</div>
<div class="div4">....</div>
</div>
Some more examples could be found HERE.
I would do it this way:
*{
margin: 0;
border: 0;
padding: 0;
box-sizing: border-box;
}
.parent{
display: flex;
padding: 15px;
}
.a, .b{
background: #ddd;
margin: 10px;
flex-basis: 20%;
}
.container{
width: 60%;
}
.container div{
background: #ddd;
margin: 10px;
}
<div class="parent">
<div class="a">div1</div>
<div class="container">
<div>div</div>
<div>div</div>
</div>
<div class="b">div2</div>
</div>