Design a layout with one div on 2 columns and 2 rows at the left, and 4 divs on 2 columns and 2 rows at the right, similar to BBC website - html

I want to design a hero section similar to BBC website. I started working on this using CSS Grid which I thought could get the same design with minimal code.
I have managed to base design but I want item1 to take 50% of the container's width and rest of the items to take 25% of space each so that it looks like the image above. I can span rows but I am not sure how I can span columns correctly, I tried this :
.item1 {
grid-column-end: span 2;
}
But it broke the design and same did happen with:
.item1 {
grid-column: auto / span 2;
}
My code:
.grid-container {
display: grid;
grid-template-columns: auto auto auto;
grid-gap: 10px;
background-color: #2196F3;
padding: 0px;
}
.grid-container > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 0px 0;
font-size: 30px;
}
.item1 {
grid-row-end: span 2;
}
.grid-container div img {width:100%; max-width:600px;}
<div class="grid-container">
<div class="item1">
<img src="https://dummyimage.com/600x400/f09c00/fafafa&text=1"/>
</div>
<div class="item2">
<img src="https://dummyimage.com/600x400/0010f0/fafafa&text=2"/>
</div>
<div class="item3">
<img src="https://dummyimage.com/600x400/5310f0/fafafa&text=3"/>
</div>
<div class="item4">
<img src="https://dummyimage.com/600x400/0010f0/fafafa&text=4"/>
</div>
<div class="item5">
<img src="https://dummyimage.com/600x400/0010f0/fafafa&text=5"/>
</div>
</div>

You could do it as below. I simplified the code by removing irrelevant code for the desired layout and added comments.
.grid-container {
background-color: #2196f3;
/* with these 3 lines below, I'm creating a grid of 4 columns and 2 rows*/
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: auto auto;
grid-gap: 10px;
}
.grid-container > div:nth-of-type(1){ /* I grab the first div */
grid-column: 1 / 3; /* I tell him to take 2 columns, 1 -> 3 with 3 excluded */
grid-row: 1 / 3; /* I tell him to take 2 rows, 1 -> 3 with 3 excluded */
}
.grid-container div img {
width: 100%;
height:100%;
object-fit:cover;
}
<div class="grid-container">
<div class="item1">
<img src="https://dummyimage.com/600x400/f09c00/fafafa&text=1" />
</div>
<div class="item2">
<img src="https://dummyimage.com/600x400/0010f0/fafafa&text=2" />
</div>
<div class="item3">
<img src="https://dummyimage.com/600x400/5310f0/fafafa&text=3" />
</div>
<div class="item4">
<img src="https://dummyimage.com/600x400/0010f0/fafafa&text=4" />
</div>
<div class="item5">
<img src="https://dummyimage.com/600x400/0010f0/fafafa&text=5" />
</div>
</div>

Related

Make a grid as big as the screen

I need the grid ad big as the page (it should touch the top the bottom and both sides) and I'd like it to be non-scrollable.
HTML:
<div class="wrapper">
<div class="prova">One</div>
<div class="prova"> </div>
<div class="prova">Three</div>
<div class="prova">Four</div>
<div class="prova"> five </div>
<div class="prova">Six</div>
<div class="prova">Seven</div>
<div class="prova">Eight</div>
<div class="prova">Nine</div>
<div class="prova">Ten</div>
<div class="prova">Eleven</div>
<div class="prova">Twelve</div>
</div>
CSS:
.wrapper {
padding-top: 10%;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
}
.prova{
border: 1px solid;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
I've read multiple questions but I couldn't find any solution that works fine for me.
As you can see in the picture above the grid doesn't touch neither the top or the bottom!
Set gird-auto-rows to use a percentage of the viewport height. Equal amounts per expected row. So in your case 25vh. Then remove any padding or margin around the grid.
html, body {
margin: 0
}
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 25vh;
width: 100%;
}
.prova{
border: 1px solid;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
<div class="wrapper">
<div class="prova">One</div>
<div class="prova"> </div>
<div class="prova">Three</div>
<div class="prova">Four</div>
<div class="prova"> five </div>
<div class="prova">Six</div>
<div class="prova">Seven</div>
<div class="prova">Eight</div>
<div class="prova">Nine</div>
<div class="prova">Ten</div>
<div class="prova">Eleven</div>
<div class="prova">Twelve</div>
</div>
If you want it to touches the top just remove the padding
And for other sides just set the width and height of the wrapper to 100vh and 100vw

How to align grid items vertically using display:grid and fill all vertical empty space? [duplicate]

This question already has answers here:
How can I make a div span multiple rows and columns in a grid?
(3 answers)
Closed 1 year ago.
I use display:grid not flex to display some divs.
Here's what my page looks like:
And here is how I would like it to look:
And here's the code:
.container {
display: grid;
grid-template-columns: 1.5fr 2fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-auto-columns: 1fr;
grid-auto-rows: 1fr;
gap: 40px 40px;
grid-auto-flow: row dense;
justify-items: stretch;
align-items: stretch;
grid-template-areas: "left1 center-div right1" "left1 center-div right2" "left2 center-div right3";
width: 100%;
height: 100%;
}
.left1 {
grid-area: left1;
}
.left2 {
grid-area: left2;
}
.center-div {
grid-area: center-div;
}
.right1 {
grid-area: right1;
}
.right2 {
grid-area: right2;
}
.right3 {
grid-area: right3;
}
<div class="container owl-carousel owl-theme">
<div class="grid-item left1">
left image 1
</div>
<div class="grid-item left2">
left image 2
</div>
<div class="grid-item center-div">
center image
</div>
<div class="grid-item right1">
right image 1
</div>
<div class="grid-item right2">
right image 2
</div>
<div class="grid-item right3">
right image 3
</div>
</div>
In short, I want to bring the divs closer so that they appear as they are in the second photo
Using CSS Grid
Following demo shows how you can achieve the desired layout using just the grid layout.
Its a 6 x 3 grid where items on the left span 3 rows each and the items on the right span 2 rows each. The item in the center spans all 6 rows.
Each grid items is adjusted in its place using the grid-row and grid-column properties.
The trick to achieving this layout is having more rows than columns.
.container {
display: grid;
grid-template-columns: 1.5fr 2fr 1fr;
grid-template-rows: repeat(6, 1fr);
grid-gap: 30px;
height: 100vh;
}
.grid-item {
background: #eee;
width: 100%;
}
.center {
grid-row: 1 / span 6;
grid-column: 2 / span 1;
}
.left1 {
grid-row: 1 / span 3;
grid-column: 1 / span 1;
}
.left2 {
grid-row: 4 / span 3;
grid-column: 1 / span 1;
}
.right1,
.right2,
.right3 {
grid-column: 3 / span 1;
}
.right1 { grid-row: 1 / span 2; }
.right2 { grid-row: 3 / span 2; }
.right3 { grid-row: 5 / span 2; }
<div class="container">
<div class="grid-item left1">left1</div>
<div class="grid-item left2">left2</div>
<div class="grid-item center">center</div>
<div class="grid-item right1">right1</div>
<div class="grid-item right2">right2</div>
<div class="grid-item right3">right3</div>
</div>
Using CSS Grid along with Flexbox
Another option is to have a 1 x 3 grid and make each grid column a flex container.
You will need to change the structure of the HTML if you use this approach.
:root {
--spacing: 30px;
}
.container {
display: grid;
grid-template-columns: 1.5fr 2fr 1fr;
grid-gap: var(--spacing);
height: 100vh;
}
.grid-item {
display: flex;
}
.grid-item div {
background: #eee;
flex-basis: 100%;
}
.col-1,
.col-3 {
flex-direction: column;
justify-content: space-between;
}
.margin-bottom {
margin-bottom: var(--spacing);
}
<div class="container">
<div class="grid-item col-1">
<div class="margin-bottom">left1</div>
<div>left2</div>
</div>
<div class="grid-item col-2">
<div>center</div>
</div>
<div class="grid-item col-3">
<div class="margin-bottom">right1</div>
<div class="margin-bottom">right2</div>
<div>right3</div>
</div>
</div>

Inserting a new div between two grid items

I have the following grid layout:
<div class="main-page">
<div class="side-bar"></div>
<div class="nav-bar"></div>
<div class="index-view"></div>
</div>
and I am trying to insert a new div between sidebar and index such that the resulting layout will be like:
<div class="main-page">
<div class="side-bar"></div>
<div class="nav-bar"></div>
<div class="profile-pane"></div>
<div class="index-view"></div>
</div>
My attempt so far has been:
.main-page {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: 72px 1fr;
height: 100%;
}
.main-page > .side-bar {
display: grid;
grid-row: 1/4;
width: 80px;
}
.main-page > .profile-pane {
width: 260px;
position: relative;
grid-row: 2/4;
}
.main-page > .index-view {
grid-row: 2/4;
}
This renders a huge space between profile and index and compresses index to the right. I've been trying different values for the grid-row property but to no avail. However, if I remove either one of profile and index, the remaining div will render nicely and right beside the sidebar. How do I achieve the second layout?
You can consider different values based on the existance of the profile element:
.main-page {
display: grid;
grid-template-columns: 80px 1fr 4fr;
grid-template-rows: 72px 1fr;
height: 200px;
margin:20px;
}
.side-bar {
grid-row: span 2;
}
.nav-bar,
.index-view {
grid-column:span 2;
}
/* Take only one clumn if profile exist*/
.profile-pane + .index-view {
grid-column:span 1;
}
/* Irrelevant code */
.main-page > * {
border:1px solid;
}
.main-page > *:before {
content:attr(class);
}
<div class="main-page">
<div class="side-bar"></div>
<div class="nav-bar"></div>
<!--<div class="profile-pane"></div>-->
<div class="index-view"></div>
</div>
<div class="main-page">
<div class="side-bar"></div>
<div class="nav-bar"></div>
<div class="profile-pane"></div>
<div class="index-view"></div>
</div>
You can achieve the desired result by setting the "grid-row: span 2" property in the sidebar to increase its height by two lines. And for the navigation bar, the "grid-column: span 2" property is to expand it into two columns
Oh yes, and do not forget to set the columns of the required width for the grid container grid-template-columns: 10% 15% 70%;
Result:
.main-page {
display: grid;
grid-template-columns: 10% 15% 70%;
}
.main-page>* {
padding: 20px;
border: 1px solid #000;
}
.side-bar {
grid-row: span 2;
}
.nav-bar {
grid-column: span 2;
}
.index-view {
min-height: 500px;
}
<div class="main-page">
<div class="side-bar">side-bar</div>
<div class="nav-bar">nav-bar</div>
<div class="profile-pane">profile-pane</div>
<div class="index-view">index-view</div>
</div>

How to display Image (and Icon) on top of Image in CSS Grid cell.

I'm trying to create a responsive grid with text and an icon on top of a picture in each grid cell. However, I can't seem to get the text to stack on top of the image.
Here is my current code:
https://codepen.io/FrazierChristie/pen/WgdEEx
<div id="igGrid">
<div class="ig1">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/3_1024x1024.jpg?v=1526628915" >
<div class="igText"> TEXT HERE </div>
</div>
<div class="ig2">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/grey9_1024x1024.jpg?v=1526628964" >
</div>
<div class="ig3">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/12345_1024x1024.jpg?v=1526629035" >
</div>
<div class="ig4">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/td1_1024x1024.jpg?v=1526628975" >
</div>
<div class="ig5">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/grey6_1024x1024.jpg?v=1526629015" >
</div>
<div class="ig6">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/BlueLS3_1024x1024.jpg?v=1535724601" >
</div>
<div class="ig7">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/Leaf1_1024x1024.jpg?v=1526629035" >
</div>
<div class="ig8">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/grey8_1024x1024.jpg?v=1526628964" >
</div>
<div class="ig9">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/td4_1024x1024.jpg?v=152662897" >
</div>
<div class="ig10">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/grey4_1024x1024.jpg?v=1526628964" >
</div>
<div class="ig11">
<img class="igImage" src="https://cdn.shopify.com/s/files/1/1535/9821/products/4a_1024x1024.jpg?v=1526628915">
</div>
</div>
and
#igGrid{
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(150px, auto);
grid-gap: 10px;
max-width: 960px;
margin: 0 auto;
text-align: center;
color: #fff;
}
#igGrid div{
background: #fff;
padding: 0px;
}
.ig1{
grid-column: 1/2;
}
.ig2{
grid-column: 2/3;
}
.ig3{
grid-column:3/5;
grid-row: 1/3;
}
.ig4{
grid-column: 1/3;
grid-row: 2/4;
}
.ig9{
grid-column: 3/5;
grid-row: 4/6;
}
.igImage{
width:100%;
height: 100%;
}
.igText{
position: absolute;
top:50%;
left: 50%;
tranfrom: translate(-50%,-50%);
}
Can anyone help at all?
Sorry about my formatting, I'm really new to all of this and just playing around really.
Thanks!
here try this.. Instead of calling the image out in your html, call it out on your css. all the grid is already formatted, you just need to enter the background:url() for every div class you created so for example...
HTML
<div class="ig1">
<h2> Text Here </h2>
</div>
CSS
.ig1 {
background:url('https://cdn.shopify.com/s/files/1/1535/9821/products/3_1024x1024.jpg?
v=1526628915');
background-repeat: no-repeat;
background-size:contain;
}
this way the img will be the background. so anything infront of the background will appear. I hope this helps!
try adding this to your css.
* {
box-sizing: border-box;
}
and I just thought of a different way of doing this. you could try..
entering the img to be 100% of its container by typing this. and also add a z-index so that you can layer anything on top of it, so like your text.
img {
width: 100%;
z-index -1;
}

How to prevent grid-row span from changing column placement?

I have a 3 X 3 CSS Grid.
I have a row in which I have three items A, B & C.
I want item C to have a rowspan of 2.
To do so, I am using grid-row: 1 / span 2;. It is taking two rows, but it's being placed in the first column instead of simply lying in the 3rd column. I don't know why this is happening.
I want item C to stay at the place where it is in the HTML.
One work around to this problem is to explicitly setting grid-column: 3 / span 1 which I don't want to do. I want items to be placed the way they are in HTML.
Is there any way to suppress this behavior?
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: 1 / span 2;
background: orange;
}
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
Another way of solving it (That points to the reason why is stating a row for the other items):
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: 1 / span 2;
background: orange;
}
.b {
grid-row: 1;
}
<div class="grid-container">
<div class="b">
<h1>A</h1>
</div>
<div class="b">
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
And the reason of this behaviour is that the more restrictive elements get positioned first. This way, the possibilities of the grid algorithm to achieve a solution are bigger.
That is, an element that has a requirement will be positioned first, elements that don't have a requirement last.
Steps 2 (for a item) and 4 (for the remaining items) in this part of the spec
If only one gets stock to a row number it will come first and stick there ahead in the flow. To avoid this, other grid items needs to be set to a defaut row as well.
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
div {
grid-row: 1;/* here is the basic fix but will set each item on first row */
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: 1 / span 2;
background: orange;
}
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
Else you need also to tell in which grid-column it should stand
.a {
grid-row: 1 / span 2;
grid-column:3;
background: orange;
}
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: 1 / span 2;
grid-column:3;
background: orange;
}
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
or let auto placement do its job while only setting how many rows to span, wich is here, in my own opinion, the most flexible way with a minimum of css rules/selector to set, too much grid kills grid :) , make it simple :
.a {
grid-row: span 2;
background: orange;
}
snippet with a few example letting the .aclass do its job without setting the column nor the row number where to stand, it will just be spanning where it stans in the flow
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: span 2;
background: orange;
}
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div class="a">
<h1>B</h1>
</div>
<div>
<h1>C</h1>
</div>
</div>
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div>
<h1>C</h1>
</div>
<div>
<h1>D</h1>
</div>
<div>
<h1>E</h1>
</div>
<div class="a">
<h1>F</h1>
</div>
<div>
<h1>G</h1>
</div>
<div>
<h1>H</h1>
</div>
</div>
<hr/>
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
<div>
<h1>D</h1>
</div>
<div>
<h1>E</h1>
</div>
<div>
<h1>F</h1>
</div>
<div>
<h1>G</h1>
</div>
<div>
<h1>H</h1>
</div>
</div>
Clearly, there's something in the spec that causes this behavior. I'm not yet sure what it is. (Update: see #Vals' answer for an explanation.)
However, here's a valid and simple solution:
Instead of:
.a {
grid-row: 1 / span 2;
}
Use:
.a {
grid-row-end: span 2;
}
From the spec:
9.3. Line-based Placement: the grid-row-start,
grid-column-start, grid-row-end, and grid-column-end
properties
The grid-row-start, grid-column-start, grid-row-end, and
grid-column-end properties determine a grid item’s size and location
within the grid by contributing a line, a span, or nothing (automatic)
to its grid placement, thereby specifying the inline-start,
block-start, inline-end, and block-end edges of its grid area.
...
For example, grid-column-end: span 2 indicates the second grid line
in the endward direction from the grid-column-start line.
Also, consider this single rule that gives you full control and makes it all work:
.a {
grid-area: 1 / 3 / 3 / 4;
}
jsFiddle
The grid-area shorthand property parses values in this order:
grid-row-start
grid-column-start
grid-row-end
grid-column-end
Note the counter-clockwise direction, which is the opposite of margin and padding.