I'm currently working on a project, in which I have to display images in a grid layout. The natural thing for me was to use CSS grid. I have a working solution, which looks good only for certain aspect ratios (portrait aspect ratios). As soon as the aspect ratio is more on the landscape side (especially 16:9), the overall grid doesn't fit the screen anymore. It seems that the images are the problem because they don't "scale" vertically.
Looks good for "portrait" aspect ratios:
Looks bad for "wide" aspect ratios:
.container {
position: fixed;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
}
.client {
display: grid;
border: 3px solid black;
grid-template-columns: 1fr 1fr;
grid-template-rows: 100px 1fr 1fr 1fr 1fr 100px;
}
.client-title {
grid-column: 1 / -1;
grid-row: 1;
}
.client-description {
grid-column: 1 / -1;
grid-row: 6;
}
.exercise-image {
object-fit: cover;
width: 100%;
height: 100%;
}
<div class="container">
<div class="client">
<div class="client-title">
Title Text 1
</div>
<!-- Repeated 8 times -->
<div class="exercise">
<img class=" exercise-image " src="https://via.placeholder.com/300.jpg">
</div>
<div class="client-description ">
Description Text 1
</div>
</div>
<div class="client ">
<div class="client-title ">
Title Text 2
</div>
<!-- Repeated 8 times -->
<div class="exercise">
<img class="exercise-image" src="https://via.placeholder.com/300.jpg">
</div>
<div class="client-description">
Description Text 2
</div>
</div>
</div>
Do you have an idea, what I miss here?
Thanks!
Set the height of the .client grid directly to full viewport height and remove height: 100vh of its grid container element .container.
That works because now the heights of the grid rows of the '.client' grid get calculated directly relative to viewport's current height.
And the containing element adapts to that childs height accordingly.
Set the min-height of the .exercise grid item, that contains each rows image, to 0 to override the default value (min-width/min-height: auto is the CSS Grid default setting) and thus, to make the image shrinkable below its own size.
CSS:
.container {
position: fixed;
top: 0;
left: 0;
// height: 100vh;
width: 100vw;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
}
.client {
display: grid;
border: 3px solid black;
grid-template-columns: 1fr 1fr;
grid-template-rows: 100px 1fr 1fr 1fr 1fr 100px;
height: 100vh; // height: 100%;
}
.client-title {
grid-column: 1 / -1;
grid-row: 1;
}
.client-description {
grid-column: 1 / -1;
grid-row: 6;
}
.exercise {
min-height: 0;
}
.exercise-image {
object-fit: cover;
width: 100%;
height: 100%;
}
Related
When i use the responsive tool of Chrome(<699pw) it create a huge gap between the footer and the div base but i want the footer a the bottom of the page. I don't know if it is the grid of the parent . I want to extend the base and make it closed to the footer so even if we extend the responsive tool. So it'has to follow the footer
header {
display: grid;
grid-template: auto;
grid-template-columns: 1fr 5fr 6fr 4fr;
align-items: center;
font-size: 30px;
position: relative;
top: 50%;
}
.parent {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-column-gap: 0px;
grid-row-gap: 0px;
}
.div1 { grid-area: 1 / 1 / 2 / 2; }
.div2 { grid-area: 1 / 2 / 2 / 3; }
.div3 { grid-area: 2 / 1 / 3 / 2; }
.div4 { grid-area: 2 / 2 / 3 / 3; }
.div5 { grid-area: 3 / 1 / 4 / 3; }
#bases{
display: grid;
grid-template: auto;
grid-template-columns: 2fr 4fr;
}
html,body{
margin: 0;
padding: 0;
}
/* Responsive */
#media (max-width: 699px){
#Titre {
display: none;
}
header {
background-color: #aa1010;
font-family: 'LexendTera';
color: white;
display: grid;
grid-template: auto;
grid-template-columns: 1fr 5fr 6fr 4fr;
align-items: center;
font-size: 10px;
position: relative;
top: 50%;
}
aside{
display: none;
}
#bases{
display: grid;
grid-template-columns: 1fr;
}
.parent{
display: grid;
align-items: center;
}
/* Mettre footer en bas de page */
footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
}
<!DOCTYPE html>
<html lang="fr">
<body>
<header>
<img src="img/logo.png" alt="logo" id="logo">
<h1 id="Titre">O'kebab</h1>
Composition
Connexion
</header>
<div id="bases">
<main>
<h1>"La maison du sandwich"</h1>
<div class="parent">
<div class="div1"><h1>Promotion</h1><p>Kebab Végetarien -50%</p> </div>
<div class="div2"><img src="img/vege.png" alt="vege"></div>
<div class="div3"><h1>Kebab du mois</h1><br><p> Kebab spicy</p></div>
<div class="div4"><img src="img/spicy.webp" alt="spicy"></div>
<div class="div5"><button>Commandez</button></div>
</div>
</main>
</div>
<footer>
<h2 id="contact">Contact</h2>
<h2 id="mention">Mentions légales</h2>
<img src="img/facebook.png" alt="facebook" id="face">
<img src="img/instagram.png" alt="instagram" id="insta">
<img src="img/iutly.png" alt="twitter" id="ly1">
<h3 id="tkt">© 2022 O'kebab</h3>
</footer>
</body>
</html>
I tried to use position:relative for the body but nothing change
The grid is fine,
In the screen size less than 699px width:
You made the header smaller by reducing its font size. And since a div is a block element by default, it would be positioned in a new line after the last element. So your "bases" div would be on top and attached beneath the header.
You forced the footer to be positioned fixed and go to the bottom of the page.
So naturally, there would be a gap between your "bases" and your "footer".
Now since the element positioned fixed is removed from the normal document flow, and no space is created for it on the page, you can't position the "bases" div relative to the "footer".
But, for fixing the gap between your divs there are many ways...
For example, you can add a height to your "bases" div and make it fill the gap.
If you want it to be responsive, instead of an absolute height you can give it a relative height, like using "%" or "vh":
#bases {
/* Relative to % of the height of the viewport */
height: 80vh;
}
And you can adjust the position of contents by "display flex" and "align-items" or maybe using padding and margins.
You can also make it "position absolute" as well and position it somewhere in the middle of the page. as I said there are many ways to fill that gap.
And a quick tip for using media queries, If you want to change an attribute of an element, you don't need to write all of its attributes again.
for example, if you have this code and you want to change its font size:
.header {
display: grid;
grid-template: auto;
grid-template-columns: 1fr 5fr 6fr 4fr;
align-items: center;
font-size: 30px;
position: relative;
top: 50%;
}
You can just change the font size, and there is no need to duplicate all of that code:
#media (max-width: 699px) {
.header {
font-size: 10px;
}
}
I think it's best if I try to explain this with a screenshot. So, I am trying to achieve this: https://freeimage.host/i/H9flW3N
My problem is when I do it with grid, the first picture is too short/height not enough to fit the whole grid cell so the gap between the upper left and lower left picture is too big.
This is what I have:
https://freeimage.host/i/H9f0KMv
Is there a way to achieve the layout from the upper picture with grid where the grid rows adjust according to a picture height? It needs to be responsive of course :/
Also how should I go about positioning the third picture, because it shouldn't be aligned with the first two. Can this be achieved with margins or?
Thank you in advance, this has been driving me insane for a few days now and I can't get it to work. I tried with flexbox, now I'm trying with grid but no result yet
Here's my code:
.fourth {
display: flex;
flex-direction: column;
align-items: center;
}
.collage2 {
display: grid;
width: 85%;
grid-auto-columns: repeat (2, 1fr);
}
.collage2 > img {
object-fit: cover;
width: 100%;
max-height: 100%;
}
.collage2 img:nth-child(3) {
grid-row: 1/2;
grid-column: 2;
}
<section class="fourth">
<div class="collage2">
<img src="/images/photo-3.jpg" alt="Man drawing on whiteboard">
<img src="/images/photo-4.jpg" alt="Ableton address on a brick wall">
<img src="/images/photo-5.jpg" alt="Man and woman working at a music studio">
</div>
Did a little play on Codepen, and I think this can give you a basic idea to start with: https://codepen.io/brandonzhang/pen/PoaJyQw?editors=1100
<div class="grid">
<img src='https://images.unsplash.com/photo-1666880147941-b145c43cfe6b?crop=entropy&cs=tinysrgb&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2Njg2ODQxMDk&ixlib=rb-4.0.3&q=80' alt=''>
<img src='https://images.unsplash.com/photo-1667489022797-ab608913feeb?crop=entropy&cs=tinysrgb&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2Njg2ODQxMDk&ixlib=rb-4.0.3&q=80' alt=''>
<img src='https://images.unsplash.com/photo-1593875460489-aa913d8a0fe2?crop=entropy&cs=tinysrgb&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2Njg2ODQxNjk&ixlib=rb-4.0.3&q=80' alt=''>
</div>
img {
width: 100%;
object-fit: cover;
}
.grid {
--gap: 8%;
display: grid;
align-items: center;
justify-items: center;
grid-template-columns: 2fr 3fr;
gap: var(--gap);
padding: var(--gap);
position: relative;
}
img:nth-of-type(2) {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
img:nth-of-type(3) {
grid-column: 2 / 3;
grid-row: 1 / 3;
height: 80%;
}
.grid::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(2 / 5 * 100% + var(--gap) * 2);
bottom: 0;
background: lightseagreen;
z-index: -1;
}
This question already has an answer here:
Why does minmax(0, 1fr) work for long elements while 1fr doesn't?
(1 answer)
Closed last year.
Problem: I am having a problem with sizing images inside css grid column/rows. I essentially object-fit: contain the imagesinside their individual cells.
The image in "SPOT 4" is not filling the given space
If you uncomment the image in "SPOT 1", it will cover the entire grid and is not confined to its own css grid cell.
I have tried setting max-width, object-fit and others on the video level and .channel-container level with no success.
Background: The .parent-trap css class is just an example height/width. This will vary, it may be the entire browser window, or it may be small so I cannot depend on any specific min/max dimensions. There are also other .display4 in the full version that sometimes shows a single video that fills the whole grid, side by side that only shows 2 at a time etc, so any specific dimensions also tend to break individual .display*
html,
body {
border: 0;
margin: 0;
height: 100%;
}
.parent-trap {
height: 540px;
width: 960px;
}
/* container for player */
.video-player {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
max-height: 100%;
max-width: 100%;
min-height: 100%;
min-width: 100%;
}
/* container for plaback control bar */
.container-controls {
height: 50px;
background-color: red;
}
/* contains all the .channel-container s */
.channel-layout-container {
display: grid;
background: #000;
background-color: blue;
flex: 1;
}
/****
**** FIX HERE
****/
.channel-container {}
img {}
/** THERE ARE OTHER DYNAMIC LAYOUTS, ISSUE IS SAME ON ALL */
/** display4 **/
.channel-layout-container.display4 {
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.channel-layout-container.display4 .channel-container:nth-child(n+5) {
flex: none;
display: none;
}
<!-- try restricting various sizes -->
<div class="parent-trap">
<!-- the classcommes that need to be transferred back over-->
<div class="video-player">
<div class="channel-layout-container display4">
<div class="channel-container" style="background-color: khaki;">
<!-- <img src="https://w.wallhaven.cc/full/3z/wallhaven-3zgz2y.png" />-->
</div>
<div class="channel-container" style="background-color: lavender;">
SPOT 2
</div>
<div class="channel-container" style="background-color: lightcoral;">
SPOT 3
</div>
<div class="channel-container" style="background-color: lightseagreen;">
<img src="https://www.google.com/favicon.ico" />
</div>
</div>
<div class="container-controls">
common controls and other info goes here
</div>
</div>
</div>
Your issue results from your grid template definition.
Replace 1fr 1fr with repeat(2, minmax(0, 1fr)).
The reason for your problem is that 1fr effectively means minmax(auto, 1fr). minmax works such that if the first argument is greater than the second, the whole minmax expression is replaced by the first argument, so your whole definition becomes
grid-template-columns: auto auto;
grid-template-rows: auto auto;
Setting minmax(0, 1fr) prevents this and effectively sets what you did by setting min-width/-height to 0.
I ended up needing 3 things, I'm not entirely sure what the min-width/height: 0 are doing to fix my issue but it works
.channel-layout-container {
min-height: 0; /* NEW */
min-width: 0; /* NEW; needed for Firefox */
}
.channel-container {
min-height: 0; /* NEW */
min-width: 0; /* NEW; needed for Firefox */
}
img {
display:block;
width :100%;
height:100%;
object-fit:cover;
}
html,
body {
border: 0;
margin: 0;
height: 100%;
}
.parent-trap {
height: 540px;
width: 960px;
}
/* container for player */
.video-player {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
max-height: 100%;
max-width: 100%;
min-height: 100%;
min-width: 100%;
}
/* container for plaback control bar */
.container-controls {
height: 50px;
min-height: 50px;
max-height: 50px;
background-color: red;
}
/* contains all the .channel-container s */
.channel-layout-container {
display: grid;
background: #000;
background-color: blue;
flex: 1;
min-height: 0; /* NEW */
min-width: 0; /* NEW; needed for Firefox */
}
/****
**** FIX HERE
****/
.channel-container {
min-height: 0; /* NEW */
min-width: 0; /* NEW; needed for Firefox */
}
img {
display:block;
width :100%;
height:100%;
object-fit:cover;
}
/** THERE ARE OTHER DYNAMIC LAYOUTS, ISSUE IS SAME ON ALL */
/** display4 **/
.channel-layout-container.display4 {
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.channel-layout-container.display4 .channel-container:nth-child(n+5) {
flex: none;
display: none;
}
<div class="parent-trap">
<!-- the classcommes that need to be transferred back over-->
<div class="video-player">
<div class="channel-layout-container display4">
<div class="channel-container" style="background-color: khaki;">
<img src="https://w.wallhaven.cc/full/3z/wallhaven-3zgz2y.png" />
</div>
<div class="channel-container" style="background-color: lavender;">
SPOT 2
</div>
<div class="channel-container" style="background-color: lightcoral;">
SPOT 3
</div>
<div class="channel-container" style="background-color: lightseagreen;">
<img src="https://www.google.com/favicon.ico" />
</div>
</div>
<div class="container-controls">
common controls and other info goes here
</div>
</div>
</div>
You can see now that changing .parent-trap dimensions keep the proper proportions , control bar is always available and just the displays adjust as necessary.
So I have this basic setup - a canvas area and an animator in a parent grid.
The parent grid is also inside another grid with one 1fr row.
I can resize the animator by dragging a resizer up and down.
canvas {
background-color: blue;
}
#grid1 {
grid-template-rows: 1fr;
}
#grid2 {
background-color: black;
display: grid;
grid-template-rows: 1fr auto;
overflow: hidden;
}
#canvas-area {
grid-row: 1;
background-color: red;
}
#animator {
grid-row: 2;
height: 200px;
}
<div id="grid1">
<div id="grid2">
<div id="canvas-area">
<canvas/>
</div>
<div id="animator"></div>
</div>
</div>
I want the canvas to be bigger than its parent and hide its overflow, but that seems to also expand the parent element.
I've already tried overflow: hidden, but that doesn't work
As a side question: I also noticed that there is a space of 4px under the canvas, why is that?
I want the canvas to be bigger than its parent and hide its overflow, but that seems to also expand the parent element.
Normally you'd add a height to the grid container so that the the 1fr in the grid-template-rows: 1fr auto is meaningful; otherwise the grid item auto-adjusts to the dimensions of its contents.
Add overflow: hidden to the grid item #canvas-area along with a fixed height to the container (say 400px as your previous jsFiddle had) - see demo below:
document.querySelector('button').onclick = () => {
document.querySelector('canvas').height = 300;
}
canvas {
background-color: blue;
}
#grid {
background-color: black;
display: grid;
grid-template-rows: 1fr auto;
width: 400px;
height: 400px; /* added a fixed height */
}
#canvas-area {
grid-row: 1;
background-color: red;
overflow: hidden; /* added */
}
#animator {
grid-row: 2;
height: 200px;
}
<div id="grid">
<div id="canvas-area">
<canvas/>
</div>
<div id="animator"></div>
</div>
<button>Change Canvas Height</button>
Note that adding min-height: 0 also does not grow the container:
document.querySelector('button').onclick = () => {
document.querySelector('canvas').height = 300;
}
canvas {
background-color: blue;
}
#grid {
background-color: black;
display: grid;
grid-template-rows: 1fr auto;
width: 400px;
height: 400px;
}
#canvas-area {
grid-row: 1;
background-color: red;
min-height: 0; /* added */
}
#animator {
grid-row: 2;
height: 200px;
}
<div id="grid">
<div id="canvas-area">
<canvas/>
</div>
<div id="animator"></div>
</div>
<button>Change Canvas Height</button>
Why so?
By default grid items have min-width: auto and min-height: auto (just like flex items). You can see some examples of of this behaviour below:
css-grid creates an imaginary column
How to make images stay within the rows of a css grid container?
and from the specs:
To provide a more reasonable default minimum size for grid items, this
specification defines that the auto value of min-width/min-height also
applies an automatic minimum size in the specified axis to grid items
whose overflow is visible and which span at least one track whose min
track sizing function is auto.
W3C
Space below canvas element?
I also noticed that there is a space of 4px under the canvas, why is that?
That is the whitespace, a characteristic of inline elements - you can remove that by making it a block element (add display: block) or adjusting vertical-align property (add vertical-align: top):
document.querySelector('button').onclick = () => {
document.querySelector('canvas').height = 300;
}
canvas {
background-color: blue;
display: block; /* added */
}
#grid {
background-color: black;
display: grid;
grid-template-rows: 1fr auto;
width: 400px;
height: 400px;
}
#canvas-area {
grid-row: 1;
background-color: red;
min-height: 0; /* added */
overflow: auto; /* added */
}
#animator {
grid-row: 2;
height: 200px;
}
<div id="grid">
<div id="canvas-area">
<canvas/>
</div>
<div id="animator"></div>
</div>
<button>Change Canvas Height</button>
I'm trying to create a CSS grid with two rows. I want the row on the bottom to be fixed to 47px tall. That's easy enough. It's the top row that is giving me trouble.
I want the top row of my CSS grid to be a minimum of 250px tall, even if there is no content in the row. But if content is in there, I want the row to expand its height up to a maximum of 303px tall. That is to say, I want the row's height to grow only if the content makes that necessary.
From what I've seen with things like grid-template-rows: minmax(250px, 303px), is that it will expand to 303px if there is enough room for it to do so.
Even if there is enough room, I don't want it to expand unless it has to - that is to say, it only expands because there's content that is taller than 250px.
I have a simple grid like this:
<div class="myGrid">
<div class="left"></div>
<div class="right"></div>
<div class="bottom"></div>
</div>
With CSS like this:
.myGrid {
display: grid;
max-height: 350px;
grid-template-rows: minmax(250px, 303px) 47px;
grid-template-columns: 1fr 2.5fr;
grid-template-areas: "a b" "c c";
}
.left {
grid-area: a;
}
.right {
grid-area: b;
}
.bottom {
grid-area: c;
}
With this code, the top row is always 303px, presumably because there's enough room to expand to that height. But I only want it to expand to that height if its content makes that necessary.
Instead of controlling the minimum and maximum heights of the row at the grid container level, control them at the grid item level.
.myGrid {
display: grid;
max-height: 350px;
grid-template-rows: auto 47px;
grid-template-columns: 1fr 2.5fr;
grid-template-areas: "a b" "c c";
}
.left {
min-height: 250px;
max-height: 303px;
grid-area: a;
background-color: aqua;
}
.right {
min-height: 250px;
max-height: 303px;
grid-area: b;
background-color: lightgreen;
}
.bottom {
grid-area: c;
background-color: orangered;
}
body {
margin: 0;
}
<div class="myGrid">
<div class="left"></div>
<div class="right"></div>
<div class="bottom"></div>
</div>
jsFiddle demo
A hack can be to set the max-height on either .left or .right, and overflow as hidden like:
.myGrid {
display: grid;
max-height: 350px;
max-width: 700px;
grid-template-rows: minmax(250px, max-content) 47px;
grid-template-columns: 33% 67%;
grid-template-areas: "a b" "c c";
}
.left {
max-height: 303px;
overflow: hidden;
grid-area: a;
}
.right {
grid-area: b;
}
.bottom {
grid-area: c;
}