Css make a grid with centered content - html

I'm trying to create a layout for print content on sticker label.
So, I create div and use display:grid; to divide space as I want.
The item1, item2, and item3 should overlap each other and centered in the cell.
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 70mm; // Seems useless
align-items: center;
}
.cell {
border-style: dashed;
width: 100mm;
height: 70mm;
align-content: center;
}
.item1 {
z-index: 0;
width: 40mm;
height: 40mm;
background-color: red;
position: relative;
}
.item2 {
z-index: 1;
width: 20mm;
height: 20mm;
background-color: blue;
position: relative;
}
.item2 {
z-index: 2;
width: 10mm;
height: 10mm;
background-color: green;
position: relative;
}
<div class="grid">
<div class="cell">
<div class="item1"></div>
<div class="item2"></div>
<img class="item3" src="./src.png" />
</div>
<div class="cell">
<div class="item1"></div>
<img class="item2" src="./src.png" />
<div class="item3"></div>
</div>
<div class="cell">
<div class="item1"></div>
<img class="item2" src="./src.png" />
<div class="item3"></div>
</div>
</div>
I can't achieve the correct result: A grid with items centered horizontally AND vertically in each cell. The cell should have precise size (100mmx70mm), 2 cells per row since the page should be printed.
Is there any CSS wizard in the audience that can help me?

All you need is absolute positioning and translate transformations based on percentage.
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 70mm; // Seems useless
align-items: center;
}
.cell {
border-style: dashed;
width: 100mm;
height: 70mm;
align-content: center;
position: relative;
}
.cell>*{
position: absolute;
left:50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
}
.item1 {
z-index: 0;
width: 40mm;
height: 40mm;
background-color: red;
}
.item2 {
z-index: 1;
width: 20mm;
height: 20mm;
background-color: blue;
}
.item2 {
z-index: 2;
width: 10mm;
height: 10mm;
background-color: green;
}
<div class="grid">
<div class="cell">
<div class="item1"></div>
<div class="item2"></div>
<img class="item3" src="./src.png" />
</div>
<div class="cell">
<div class="item1"></div>
<img class="item2" src="./src.png" />
<div class="item3"></div>
</div>
<div class="cell">
<div class="item1"></div>
<img class="item2" src="./src.png" />
<div class="item3"></div>
</div>
</div>

Related

How to create a flexbox grid with a column span and spacing between elements

I am trying to create a flexbox grid which should look like that
The basic grid layout is pretty easy to create, but I have a very hard time adding the spacing between the elements. As you can see in the code snippet, the spacing in the second line is not working properly.
#flexContainer {
display: flex;
flex-direction: column;
gap: 16px;
height: 200px;
width: 600px;
}
.rowContainer {
display: flex;
flex-direction: row;
gap: 16px;
}
.thirdElement {
flex-grow: 1;
height: 40px;
background-color: red;
}
.twoThirdsElement {
flex-grow: 2;
height: 40px;
background-color: red;
}
<div id="flexContainer">
<div class="rowContainer">
<div class="thirdElement">
</div>
<div class="thirdElement">
</div>
<div class="thirdElement">
</div>
</div>
<div class="rowContainer">
<div class="twoThirdsElement">
</div>
<div class="thirdElement">
</div>
</div>
</div>
This looks to me like a three column grid with the fourth item spanning two colums.
Here's a simplified version. Obviously you'll want to style the items as you need them.
#flexContainer {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 16px;
height: 200px;
width: 600px;
}
#flexContainer>* {
background-color: red;
}
.twoThirdsElement {
grid-column: auto / span 2;
}
<div id="flexContainer">
<div>
</div>
<div>
</div>
<div>
</div>
<div class="twoThirdsElement">
</div>
<div>
</div>
</div>
Use CSS grid
#flexContainer {
display: flex;
flex-direction: column;
gap: 16px;
}
.rowContainer {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 16px;
}
.thirdElement {
height: 40px;
background-color: red;
}
.twoThirdsElement {
grid-column:span 2;
height: 40px;
background-color: red;
}
<div id="flexContainer">
<div class="rowContainer">
<div class="thirdElement">
</div>
<div class="thirdElement">
</div>
<div class="thirdElement">
</div>
</div>
<div class="rowContainer">
<div class="twoThirdsElement">
</div>
<div class="thirdElement">
</div>
</div>
</div>
You not need to <div class="rowContainer">. It fixes only with one flex property for #flexContainer.
#flexContainer {
display: flex;
flex-wrap: wrap;
height: calc(80px + (600px / 20)); /* (600px/20) == 5% of 600px. result = 80px + 5%(600px). it is for a gap between rows that is equal with gap: 5%; for columns.*/
align-content: space-between;
gap: 5%;
width: 600px;
}
.thirdElement {
flex-basis: 30%;
height: 40px;
background-color: red;
}
.twoThirdsElement {
flex-basis: 65%;
height: 40px;
background-color: red;
}
<div id="flexContainer">
<div class="thirdElement">
</div>
<div class="thirdElement">
</div>
<div class="thirdElement">
</div>
<div class="twoThirdsElement">
</div>
<div class="thirdElement">
</div>
</div>

HTML make left and right div with left-one position:fixed

I want to create page with navigation menu on left side which will be fixed there.
In the center of the screen should be main content of page.
I made this:
HTML:
<div>
<Sidepanel></Sidepanel>
<div class="content">
<div class="item">
<img src="#/assets/1.jpg">
</div>
<div class="item">
<img src="#/assets/2.jpg">
</div>
<div class="item">
<img src="#/assets/3.jpg">
</div>
<div class="item">
<img src="#/assets/4.jpg">
</div>
</div>
</div>
HTML for sidepanel:
<div class="Sidepanel">
<div>
Home
</div>
<div>
1234
</div>
<div>
Settings
</div>
</div>
CSS:
.Sidepanel {
background-color: #5555FF;
float: left;
padding: 1em;
/*width: 200px;*/
height: 100%;
overflow: auto;
position: fixed;
}
.Sidepanel div {
margin: 5% 0 5% 0;
}
a {
color: black;
font-size: calc(1em + 1vw);
}
body {
margin: 0
}
.content {
-webkit-columns: 2 200px;
-moz-columns: 2 200px;
columns: 2 200px;
}
.content img {
width: 90%;
object-fit: cover;
}
And on the resulting page right div goes under left. It works well if I remove position:fixed, but then I loose fixed menu on scroll.
You can try with grid. Pls. look at snippet below:
.Sidepanel {
background-color: #5555FF;
padding: 1em;
height: 100%;
overflow: auto;
position: fixed;
grid-column: 1;
}
.Sidepanel div {
margin: 5% 0 5% 0;
}
a {
color: black;
font-size: calc(1em + 1vw);
}
body {
margin: 0
}
.container {
display: grid;
grid-template-columns: minmax(0,200px) 1fr;
}
.content {
-webkit-columns: 2 200px;
-moz-columns: 2 200px;
columns: 2 200px;
grid-column: 2;
justify-self: start;
}
.content img {
width: 90%;
object-fit: cover;
}
#media (max-width: 500px) {
.container {
grid-template-columns:30% 1fr;
}
}
<div class="container">
<Sidepanel>
<div class="Sidepanel">
<div>
Home
</div>
<div>
1234
</div>
<div>
Settings
</div>
</div>
</Sidepanel>
<div class="content">
<div class="item">
<img src="https://picsum.photos/200">
</div>
<div class="item">
<img src="https://picsum.photos/200">
</div>
<div class="item">
<img src="https://picsum.photos/200">
</div>
<div class="item">
<img src="https://picsum.photos/200">
</div>
</div>
</div>

Div under grid in flexbox

I have a layout that is a sidebar and a grid both wrapped in a flexbox. I'd like to put a div underneath the grid so it can have prev/next buttons, like in this image, but I can't figure out how to do that. The grid resizes itself with the window so the grid can take as many rows as necessary and then the div should go below that, and be as wide as the grid.
This is what I have, but the div is on the right of the grid:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Boardgame Database</title>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
aside {
background-color: red;
flex: 1;
min-width: 250px;
}
.grid-container {
flex: 4;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
#flex-container {
display: flex;
flex-direction: row;
min-height: 100vh;
}
</style>
</head>
<body>
<div id="flex-container">
<aside class="sidebar">
</aside>
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>
Checkout the following Code.
#main{
display :flex;
}
#sidebar{
width:70px;
height: 300px;
border: solid black 1px;
}
#grid-area{
width:200px;
height: 300px;
border: solid black 1px;
display: block;
}
#grid{
width:200px;
height: 250px;
border: solid black 1px;
display: block;
}
<div id="main">
<div id="sidebar"></div>
<div id="grid-area">
<div id="grid"></div>
<div id="button">next / prev</div>
</div>
</div>
You should use nested flex containers. Section and bottom div should be wrapped inside another flex container with flex direction to column.
So outer flex will make sidebar & inner flex container to be side by side.
Or just use a normal div container instead of flex.
here is another example only with grid keeping the pre/next button at the bottom of the viewport:
body {
margin: 0;
}
#grid-container {
display: grid;
height: 100vh;
grid-template-columns: minmax(250px, 1fr) 4fr;
grid-template-rows: 1fr auto;
}
aside {
background-color: red;
border: 1px solid;
margin: 0.25em;
grid-row: span 2;
grid-column: 1;
}
section,
#page-buttons {
grid-column: 2;
border: solid 1px;
margin: 0.25em;
}
section {
overflow: auto;
}
#page-buttons {
display: flex;
gap: 1em;
padding: 0.5em;
background: lightgray;
justify-content: center;
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
<div id="grid-container">
<aside class="sidebar">
</aside>
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>

flexbox wrapping with items of varying size

Can I achieve this layout with flexbox with the below document structure?
I want the big <img> on the left with two smaller images on the right and wrapping.
This is what I did, with display: flex on gallery-container and flex-wrap.
.container {
height: 100%;
}
.container .gallery-container {
background-color: #f6f6f6;
display: flex;
flex-wrap: wrap;
width: 300px;
align-items: flex-start;
}
.container .gallery-container .gallery-big-image {
display: block;
width: 200px;
height: 200px;
background: lavender;
}
.container .gallery-container .gallery-small-img {
display: block;
width: 100px;
height: 100px;
background-color: purple;
}
<div class="container">
<div class="gallery-container">
<div class="gallery-big-image">big</div>
<div class="gallery-small-img">small</div>
<div class="gallery-small-img">small</div>
<div class="gallery-small-img">small</div>
<div class="gallery-small-img">small</div>
<div class="gallery-small-img">small</div>
</div>
</div>
(codepen)
The layout is clunky and inefficient with flexbox, for reasons explained here: CSS-only masonry layout
However, the layout is relatively simple and easy with CSS Grid.
No changes to HTML.
.gallery-container {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
grid-auto-rows: 100px;
width: 300px;
background-color: #f6f6f6;
}
.gallery-big-image {
grid-column: span 2;
grid-row: span 2;
background: lavender;
}
.gallery-small-img {
background-color: purple;
color: white;
}
<div class="container">
<div class="gallery-container">
<div class="gallery-big-image">big</div>
<div class="gallery-small-img">small 1</div>
<div class="gallery-small-img">small 2</div>
<div class="gallery-small-img">small 3</div>
<div class="gallery-small-img">small 4</div>
<div class="gallery-small-img">small 5</div>
<div class="gallery-small-img">small 6 (continues wrapping)</div>
<div class="gallery-small-img">small 7 (continues wrapping)</div>
</div>
</div>
How about using grid layout instead?
.container {
height: 100%;
}
.gallery-container {
background-color: #f6f6f6;
width: 300px;
height: 100px;
display: grid;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(3, 1fr);
}
.gallery-img {
background: purple;
width: 100px;
height: 100px;
}
.gallery-img-large {
background: lavender;
width: 200px;
height: 200px;
grid-column-start: 0;
grid-column-end: span 2;
grid-row-start: 0;
grid-row-end: span 2;
}
<div class="container">
<div class="gallery-container">
<div class="gallery-img-large">big</div>
<div class="gallery-img">small</div>
<div class="gallery-img">small</div>
<div class="gallery-img">small</div>
<div class="gallery-img">small</div>
<div class="gallery-img">small</div>
</div>
</div>

How to change column span to row span by CSS FLEX for RWD

I want to use same HTML structure to display a Table that made of FLEX on the desktop and mobile, but I have no idea to change column span to row span, I know position: absolute it's not a good idea for maintaining
codepen
.wrapper {
display: flex;
}
.block {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
.block1 {
background-color: cadetblue;
}
.block2 {
background-color: cornflowerblue;
}
.block3 {
background-color: beige;
}
.col-span {
height: 100%;
}
/* row span */
.row-span-sample {
position: relative;
}
.row-span {
width: 200%;
position: absolute;
left: -100%;
}
<h1>column span on Desktop</h1>
<div class="wrapper">
<div class="row">
<div class="block block1 col-span">1</div>
</div>
<div class="row">
<div class="block block2">2</div>
<div class="block block3">3</div>
</div>
</div>
<h1>row span on mobile</h1>
<div class="wrapper">
<div class="row row-span-sample">
<div class="block block1">1</div>
</div>
<div class="row row-span-sample">
<div class="block block2">2</div>
<div class="block block3 row-span">3</div>
</div>
</div>
Can I change it without position: absolute?
Here's a very simple solution using CSS Grid Layout and a media query.
No absolute positioning.
No nested containers.
.wrapper {
display: grid;
grid-template-columns: 200px 200px;
grid-template-rows: 200px 200px;
grid-template-areas:
"one two"
"one three";
}
#media (max-width: 700px) {
.wrapper {
grid-template-areas:
"one two"
"three three";
}
}
.block1 { grid-area: one; background-color: cadetblue; }
.block2 { grid-area: two; background-color: cornflowerblue; }
.block3 { grid-area: three; background-color: beige; }
.block {
display: flex;
justify-content: center;
align-items: center;
font-size: 2em;
}
<div class="wrapper">
<div class="block block1">1</div>
<div class="block block2">2</div>
<div class="block block3">3</div>
</div>
revised codepen
You can do this:
.wrapper {
display: flex;
}
.block {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
.block1 {
background-color: cadetblue;
}
.block2 {
background-color: cornflowerblue;
}
.block3 {
background-color: beige;
}
.col-span {
height: 100%;
}
/* row span */
.row-span-sample {
position: relative;
}
.row-span {
width: 200%;
position: relative;
left: 0;
left: -100%;
}
<h1>column span on Desktop</h1>
<div class="wrapper">
<div class="row">
<div class="block block1 col-span">1</div>
</div>
<div class="row">
<div class="block block2">2</div>
<div class="block block3">3</div>
</div>
</div>
<h1>row span on mobile</h1>
<div class="wrapper">
<div class="row row-span-sample">
<div class="block block1">1</div>
</div>
<div class="row row-span-sample">
<div class="block block2">2</div>
<div class="block block3 row-span">3</div>
</div>
</div>
What have I done? Just change absolute value from position property, and change it to relative.
And the set left property to 0.
And why this works? Because, if you have a position defined (relative or absolute) then you can set the position (because we are get used to set them only when absolute positions are present).
Also, you can set it without left: 0; statment. Relative positions are better than absolute ones, but you need to know how them works.