I'm trying to take a single image and centre it using CSS grid, both as a way to teach myself grid and because my page calls for a single, centred image. The image is centring left-to-right but not top-to-bottom. It sits right at the top. I made the image smaller to make viewing it for test purposes easier. The size of my image is less important than its placement. What am I doing wrong?
Also, I want this in a 3x3 grid, not some other number value.
.wrapper {
display: grid;
display: flex;
justify-content: center;
}
.ConstructGrid {
justify-items: center;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(3, 1fr);
grid-gap: 1px;
grid-template-areas: ". . ." ". picture ." ". . .";
}
<div class="wrapper">
<div class="ConstructGrid">
<img class="picture" src="http://www.cafenocturne.com/images/Under_Construction.png" border="0" width="400">
</div>
</div>
It's easier than you think.
the container should be the grid, within you can set the child in its area/cell.
an height or min-height is also required even if 1fr would manage some height
body {
margin:0;
}
.wrapper {/* i draw the grid , i'm the boss !*/
height: 100vh;/* let me lay from top to bottom. I'm the boss, i want it whole */
display: grid;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(3, 1fr);
grid-gap: 1px;
grid-template-areas: ". . ." ". picture ." ". . .";
}
.ConstructGrid {
grid-area: picture;/* tell me where to be, i'm the prisoner */
margin:auto;/* let me be in the center of my area/cell :) */
}
<div class="wrapper">
<div class="ConstructGrid">
<img class="picture" src="http://www.cafenocturne.com/images/Under_Construction.png" border="0" width="400">
</div>
</div>
You didn't use the grid. Because you didn't set display:grid for .ConstructGrid. You can use only flexbox to center the image. Also you should set height: 100% to center it vertically.
html,
body,
.wrapper,
.ConstructGrid {
height: 100%;
}
.ConstructGrid {
display: flex; /* this can be display: grid also */
justify-content: center;
align-items: center;
}
<div class="wrapper">
<div class="ConstructGrid">
<img class="picture" src="http://www.cafenocturne.com/images/Under_Construction.png" border="0" width="400">
</div>
</div>
You should't have both display grid and display flex at the same block of code, otherwise, it will overwritten by the other.
In your code you have display:flex just below of display grid.
Display grid will apply when you remove display flex within .wrapper.
I would solve it like that to reserve the centered Area for the image. I use .picture-container as the wrap-element for the Image and use responsive widths and heights to get it centered right. Flex is only used inside the Wrap-Element for the Image so it doesnt interfere with the Css-Grid:
body{
height: 100vh;
width: 100vw;
padding: 0;
margin: 0;
}
.wrapper {
height: 100%;
width: 100%;
display: grid;
justify-items: center;
grid-template-rows: auto;
grid-template-columns: 25% 25% 25% 25%;
grid-template-areas:
". . . ."
" . image image ."
". . . .";
}
.picture-container{
grid-area: image;
display: flex;
align-items: center;
justify-content: center;
}
<div class="wrapper">
<div class="picture-container">
<img class="picture" src="http://www.cafenocturne.com/images/Under_Construction.png" border="0">
</div>
</div>
I also always prefer to set a height and width for your whole Area in cases like this, thats why i added them to the body. That makes it way easier to position Elements.
Related
I am trying to come up with a solution for advanced layout. I decided to use a css grid as it seemed to be the best match for my needs.
The requirements:
Header - consists of three elements - logo, search bar and menu
search bar should be aligned with the main content if space allows, i.e. on small screen search bar doesn't need to start where the main content starts but it should end where main content ends or take all available space
Main - consists of content and sidebar- should be centred and take max 100rem width space
content should be 2 times bigger than the sidebar
main content should have at least 1rem space from left and right
This is how it looks now. It matches my requirements on big screens (4k) but when the screen gets smaller it gets messy. I would really like to avoid any javascript and solve this with pure CSS if possible.
How would you approach this problem? I am now more inclining that this is not solvable with pure CSS and JS is needed. (Probably some resize observer on main-content element)
Examples:
Big screen -> alignment is correct ✔️
Small screen -> alignment is not correct. ❌ The search box should be within the black "brackets"
Even smaller screen -> alignment is not correct too. ❌ The search box should expand up to the black line
html,
body {
padding: 0;
margin: 0;
}
body {
font-family: sans-serif;
display: grid;
grid-template-columns: minmax(1rem, 1fr) minmax(min-content, 100rem) minmax(
1rem,
1fr
);
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
". main .";
min-height: 100vh;
}
.header {
padding: 1rem 1rem;
background: green;
grid-area: header;
display: grid;
grid-template-columns: minmax(max-content, 1fr) minmax(min-content, 100rem) minmax(
max-content,
1fr
);
}
.search-box {
background: yellow;
max-width: calc(2/3 * 100%);
}
.logo {
background: yellowgreen;
min-width: 5rem;
}
.menu {
background: brown;
}
.main {
grid-area: main;
display: flex;
}
.main-content {
background: red;
flex: 2;
}
.sidebar {
background: blue;
flex: 1;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<header class="header">
<div class="logo">Logo</div>
<div class="search-box">
Search box should should match main content position
</div>
<div class="menu">Menu with two submenus at least</div>
</header>
<main class="main">
<section class="main-content">Main content</section>
<aside class="sidebar">Sidebar</aside>
</main>
</body>
</html>
Sandbox available here
I'm trying to position images the way shown in the picture using CSS Grid and I can't find a right solution.
Right now I'm simply changing the grid flow to column, but the grid elements don't jump to another row when they meet the end of the container - they resize it and stay in the same, first row.
I tried to use grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)) - it solves this jump to another line issue, but it gives all the elements a fixed width whereas some images are not that wide. It creates empty holes between images which I'd like to avoid.
Any ideas on how to accomplish it?
wrong solution 1
Code from the image above:
container {
display: grid;
grid-gap: 1rem;
grid-auto-flow: column;
}
photo { // all container's elements have this class
height: 10rem;
width: auto;
}
wrong solution 2
Code from the image above:
container {
display: grid;
grid-gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}
photo {
height: 10rem;
max-width: 100%;
}
You see, this is tusk for flex, not for grid. Using grid means columns with same width on each row. No need here at all.
html {
font-size: 10px;
}
.conteiner {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.photo {
height: 10rem;
margin: 0 1rem 1rem 0;
}
.photo img {
width: auto;
height: 100%;
}
<div class="conteiner">
<div class="photo"><img src="https://via.placeholder.com/500x200"></div>
<div class="photo"><img src="https://via.placeholder.com/300x200"></div>
<div class="photo"><img src="https://via.placeholder.com/200x200"></div>
<div class="photo"><img src="https://via.placeholder.com/400x200"></div>
<div class="photo"><img src="https://via.placeholder.com/500x200"></div>
<div class="photo"><img src="https://via.placeholder.com/300x200"></div>
<div class="photo"><img src="https://via.placeholder.com/200x200"></div>
</div>
Although I'm using Justified gallery jQuery plugin, if I wand all images in each row to fill all the width.
This is something that I've been struggling with for a while, but I can't seem to find a way to do it.
If you have an odd number of items in grid and you want 2 items per row (1fr 1fr), you end up with a single item in the last row that is left-centered.
I just want to make it centered so it looks nicer.
Here's a picture too.
You can try something like this jsfiddle:
/* visibility properties */
body {
width: 60%;
margin: 5% auto;
}
div {
margin: 3%;
width: 100px;
height: 100px;
background-color: black;
justify-self: center;
}
div:nth-of-type(2n) {
background-color: red;
}
/* actual code: */
section {
display: grid;
grid-template-columns: 1fr 1fr;
}
#last-div {
grid-column: 1 / span 2;
}
<section>
<div>
</div>
<div>
</div>
<div>
</div>
<div>
</div>
<div id="last-div">
</div>
</section>
Get more info on CSS Grid: complete-guide-grid
You could try something like this since I faced a similar issue in one of my earlier projects.
grid-template-columns : repeat(auto-fit, minmax(<minSize>, 1fr));
Set minSize to whatever minimum width you want an element to occupy.
This is easiest to explain with an example:
.grid {
display: grid;
grid-gap: 5px 10px;
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
}
.grid>div {
background-color: yellow;
white-space: nowrap;
}
<div class="grid">
<div>foo</div>
<div>foo bar</div>
<div>eg ergerg</div>
<div>fo eagro</div>
<div>4ergearg ergearg er</div>
<div>earg erg</div>
<div>bverbr</div>
<div> eargerg </div>
</div>
I want to size all the columns such that they're the same width as the widest column, in this case the one that says "4ergearg ergearg er".
I don't know its width, thus I don't know what to replace that 80px with. min-content, max-content, and auto don't seem to work.
In other words, i want to stretch the columns to prevent the content from overflowing:
I'm doing some testing with the css-grid spec and am encountering an issue on my first test. I wanted to create a centered grid with 3 columns and have divs inside the grid fill the width of the columns. This works but i was not expecting the 1px margin on the right see:
.wrapper {
max-width: 400px;
margin: 0 auto;
background-color: red;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.cell {
background-color: grey;
}
<div class="wrapper">
<div class="grid">
<div class="cell">a</div>
<div class="cell">b</div>
<div class="cell">c</div>
</div>
</div>
I expect this has to do with a percentage rounding issue. If you scale the browser you see that the margin sometimes disappears.
I know i can fix this with flexbox and let the cell grow, but i'd rather know how to handle this with css-grid.
It's a math and could not be fixed. For example, if you divide 100 to 3, you will get something like 33.33333333333333..........
By the way, you could use
grid-template-columns: repeat(3, 1fr);
Instead of
grid-template-columns: 1fr, 1fr, 1fr;