Very beginner to HTML/CSS and I need some help with fitting in image inside a CSS Grid.
I have created a simple CSS grid and when I'm trying to fit an image inside one of the grid, I was able to get width to fit properly, but the height is something that will not change.
I've tried obejct-fit, max-height with ratios...etc.
Would you please help and guide me on how to get this done?
This is my codepen currently working on: https://codepen.io/jyjang703/pen/poodOgw
#main {
min-height: 100vh;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 250px 300px 300px auto;
grid-gap: 10px;
background-color: white;
grid-template-areas: "header header header header" "section1 section2 section3 section4" "footer footer footer footer";
}
#title {
grid-area: header;
border: 1px solid red;
background-color: red;
text-align: center;
}
#section1 {
grid-area: section1;
border: 1px solid red;
width: 100%;
}
#section1 img {
object-fit: cover;
position: relative;
overflow: hidden;
max-width: 100%;
max-height: 100%;
}
#section2 {
grid-area: section2;
border: 1px solid red;
}
#section3 {
grid-area: section3;
border: 1px solid red;
}
#section4 {
grid-area: section4;
border: 1px solid red;
}
#footer {
grid-area: footer;
border: 1px solid red;
}
<main id="main">
<header id="title">
<h1> Allen Iverson</h1>
</header>
<section id="section1">
<div id="img-div">
<figure>
<img src="https://fsa.zobj.net/crop.php?r=FwHUQXbzIfSpz4awUIaTcY3NIgHVe1mSFMPlsB6rpnNmbj9mHPRpVHtH7c8RgxuGUffOqlWYgSbRNw4hXsKEL4NpVjgwRglygtByR-SVELuRZrvPVOfhBVpCkcS0FNh74XcecRFJpdkNtQwOy_rZO2Ftc5H606i6-pDgEjbe2Aqrn3yUNiwkTPLkq34" alt="">
<figcaption>
It's not about size, it's about size of your heart
</figcaption>
</figure>
</div>
</section>
<section id="section2">
</section>
<section id="section3">
</section>
<section id="section4">
</section>
<footer id="footer">
I am a Footer
</footer>
</main>
You should remove the #img-div. Convert the figure to a flexbox, and constrain it's height:
#section1 figure {
display: flex;
flex-direction: column;
height: 100%;
margin: 0;
padding: 0.5em;
box-sizing: border-box;
}
Set the imgs flex to 1, and use min-height: 0 to let it shrink:
#section1 img {
display: block;
object-fit: scale-down;
max-width: 100%;
flex: 1;
min-height: 0;
}
Example (click run and then full page):
#main {
min-height: 100vh;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 250px 300px 300px auto;
grid-gap: 10px;
background-color: white;
grid-template-areas: "header header header header" "section1 section2 section3 section4" "footer footer footer footer";
}
#title {
grid-area: header;
border: 1px solid red;
background-color: red;
text-align: center;
}
#section1 {
grid-area: section1;
border: 1px solid red;
}
#section1 figure {
display: flex;
flex-direction: column;
height: 100%;
margin: 0;
padding: 0.5em;
box-sizing: border-box;
text-align: center;
}
#section1 img {
object-fit: scale-down;
max-width: 100%;
flex: 1;
min-height: 0;
}
#section2 {
grid-area: section2;
border: 1px solid red;
}
#section3 {
grid-area: section3;
border: 1px solid red;
}
#section4 {
grid-area: section4;
border: 1px solid red;
}
#footer {
grid-area: footer;
border: 1px solid red;
}
<main id="main">
<header id="title">
<h1> Allen Iverson</h1>
</header>
<section id="section1">
<figure>
<img src="https://fsa.zobj.net/crop.php?r=FwHUQXbzIfSpz4awUIaTcY3NIgHVe1mSFMPlsB6rpnNmbj9mHPRpVHtH7c8RgxuGUffOqlWYgSbRNw4hXsKEL4NpVjgwRglygtByR-SVELuRZrvPVOfhBVpCkcS0FNh74XcecRFJpdkNtQwOy_rZO2Ftc5H606i6-pDgEjbe2Aqrn3yUNiwkTPLkq34" alt="">
<figcaption>
It's not about size, it's about size of your heart
</figcaption>
</figure>
</section>
<section id="section2">
</section>
<section id="section3">
</section>
<section id="section4">
</section>
<footer id="footer">
I am a Footer
</footer>
</main>
Related
I'm trying to make the div with the class side-panel-content scrollable when it's content is big, overflow-y: scroll; doesn't work in this case.
The idea here, is to make the full page take the viewport, which works when the .long-content div has no height, but if it has a long height this shouldn't make it's container to grow more, and should be scrollable instead.
Here is a full example:
html, body {
height: 100%;
}
.main {
height: 100%;
display: grid;
grid-template-rows: auto 1fr auto;
}
header, footer {
height: 80px;
background-color: yellow;
}
.content-wrapper {
height: 100%;
width: 100%;
display: grid;
grid-template-rows: auto 1fr;
}
.title {
padding: 24px;
width: 100%;
}
.main-content {
width: 100%;
display: grid;
gap: 24px;
grid-template-columns: 1fr 350px;
justify-content: space-around;
}
.main-panel {
display: grid;
grid-template-rows: auto 1fr;
border: 2px solid red;
}
.side-panel {
height: 100%;
width: 100%;
}
.side-panel-wrapper {
height: 100%;
background: #f8f9fa;
box-shadow: 0px 4px 10px rgb(0 0 0 / 10%);
display: grid;
grid-template-rows: auto 1fr;
}
.side-panel-header {
background-color: #ffffff;
padding: 24px;
border-bottom: 2px solid #e6e9f0;
}
.side-panel-content {
overflow-y: scroll;
}
.long-content {
height: 3000px;
}
<html>
<body>
<div class="main">
<header><h1>Header</h1></header>
<div class="content">
<div class="content-wrapper">
<div class="title">
<h1>Title</h1>
</div>
<div class="main-content">
<div class="main-panel">
<div>
<h2>
Main panel title
</h2>
<p>
Main panel content
</p>
</div>
</div>
<div class="side-panel">
<div class="side-panel-wrapper">
<div class="side-panel-header">
Side panel header
</div>
<div class="side-panel-content">
<div class="long-content">
long content
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer><h1>Footer</h1></footer>
</div>
</body>
</html>
The solution for this is to use an absolute positioning for the child div that has a long height.
html, body {
height: 100%;
}
.main {
height: 100%;
display: grid;
grid-template-rows: auto 1fr auto;
}
header, footer {
height: 80px;
background-color: yellow;
}
.content-wrapper {
height: 100%;
width: 100%;
display: grid;
grid-template-rows: auto 1fr;
}
.title {
padding: 24px;
width: 100%;
}
.main-content {
width: 100%;
display: grid;
gap: 24px;
grid-template-columns: 1fr 350px;
justify-content: space-around;
}
.main-panel {
display: grid;
grid-template-rows: auto 1fr;
border: 2px solid red;
}
.side-panel {
height: 100%;
width: 100%;
}
.side-panel-wrapper {
height: 100%;
background: #f8f9fa;
box-shadow: 0px 4px 10px rgb(0 0 0 / 10%);
display: grid;
grid-template-rows: auto 1fr;
}
.side-panel-header {
background-color: #ffffff;
padding: 24px;
border-bottom: 2px solid #e6e9f0;
}
.side-panel-content {
overflow: auto;
position: relative;
height: 100%;
}
.long-content {
position: absolute;
top: 0;
height: 3000px;
}
<html>
<body>
<div class="main">
<header><h1>Header</h1></header>
<div class="content">
<div class="content-wrapper">
<div class="title">
<h1>Title</h1>
</div>
<div class="main-content">
<div class="main-panel">
<div>
<h2>
Main panel title
</h2>
<p>
Main panel content
</p>
</div>
</div>
<div class="side-panel">
<div class="side-panel-wrapper">
<div class="side-panel-header">
Side panel header
</div>
<div class="side-panel-content">
<div class="long-content">
long content
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer><h1>Footer</h1></footer>
</div>
</body>
</html>
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 months ago.
Improve this question
I use grids to customise my html layout and it does not work as I want. I want my nav to take all available width.
Here is my code:
header {
text-align: center;
grid-area: header;
border: solid;
}
#nav1 {
text-decoration: none;
border: solid;
background-color: green;
grid-area: MH;
width: 1fr;
text-align: center;
}
#nav2 {
text-decoration: none;
border: solid;
background-color: red;
grid-area: MC;
width: 1frs;
text-align: center;
}
#nav3 {
text-decoration: none;
border: solid;
background-color: yellow;
grid-area: start;
width: 1fr;
text-align: center;
}
footer {
grid-area: footer;
border: solid;
background-color: orange;
margin-top: 0px;
height: 100px;
}
main {
text-decoration: none;
border: solid;
background-color: gray;
grid-area: main;
height: 500px;
color: #ff00eb;
border-color: black;
}
aside {
width: 0.5fr;
border: solid;
background-color: purple;
grid-area: aside;
}
#big-container,
nav {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas: 'header header header' 'MH MC start' 'main main aside' 'footer footer footer ';
grid-gap: 0px;
padding: 0px;
<!-- detta är min header-->
<header>
<h1></h1>
</header>
<div id="big-container">
<nav>
mitt hus
min calender
main
</nav>
<main>
main
</main>
<aside>
aside
</aside>
<footer>
footer
</footer>
</div>
I would assign to the nav bar the display flex attribute. Like that:
header {
text-align: center;
grid-area: header;
border: solid;
}
footer {
grid-area: footer;
border: solid;
background-color: orange;
margin-top: 0px;
height: 100px;
}
main {
text-decoration: none;
border: solid;
background-color: gray;
grid-area: main;
height: 500px;
color: #ff00eb;
border-color: black;
}
aside {
width: 0.5fr;
border: solid;
background-color: purple;
grid-area: aside;
}
#big-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas: 'header header header' 'MH MC start' 'main main aside' 'footer footer footer ';
grid-gap: 0px;
padding: 0px;
}
nav {
width: 100%;
background: lightblue;
display: flex;
justify-content: center;
}
nav > a {
display: block;
text-decoration: none;
border: solid;
text-align: center;
width:100%;
}
nav > a:nth-child(1) {
background-color: green;
}
nav > a:nth-child(2) {
background-color: green;
}
nav > a:nth-child(3) {
background-color: green;
}
<!-- detta är min header-->
<header>
<h1></h1>
</header>
<nav>
mitt hus
min calender
main
</nav>
<div id="big-container">
<main>
main
</main>
<aside>
aside
</aside>
<footer>
footer
</footer>
</div>
Here is a simplified version (in terms of code) of what you wanna achieve:
body {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "header header header" "nav nav nav" "main main aside" "footer footer footer ";
}
header {
text-align: center;
grid-area: header;
border: solid;
}
nav {
grid-area: nav;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
#nav1 {
text-decoration: none;
border: solid;
background-color: green;
text-align: center;
}
#nav2 {
text-decoration: none;
border: solid;
background-color: red;
text-align: center;
}
#nav3 {
text-decoration: none;
border: solid;
background-color: yellow;
text-align: center;
}
main {
text-decoration: none;
border: solid;
background-color: gray;
grid-area: main;
height: 500px;
color: #ff00eb;
border-color: black;
}
aside {
width: 0.5fr;
border: solid;
background-color: purple;
grid-area: aside;
}
footer {
grid-area: footer;
border: solid;
background-color: orange;
margin-top: 0px;
height: 100px;
}
<header>
header
</header>
<nav>
mitt hus
min calender
main
</nav>
<main>
main
</main>
<aside>
aside
</aside>
<footer>
footer
</footer>
Try to make this:
Article and Aside are the same width
I don't know if the floating is wrong, or other. even I make the margin to 0, the Article box will drop below to Aside. And I don't why after I float the box, some of the borderlines will overlap but the footer won't. And there are some requirements.
The border is 3px.
The height of each box is 200px. Article and Aside are the same width
header,main,aside,article,footer{
background-color: lightblue;
border: 3px solid red;
height: 200px;
margin: 0;
}
header {
}
main {
width: 60%;
float: left;
}
aside{
width: 20%;
float: left;
}
article {
width: 20%;
float: right;
}
footer{
clear: both;
}
<header>
<h2>Header</h2>
</header >
<main>
<h2>Main</h2>
</main>
<aside>
<h2>Aside</h2>
</aside>
<article>
<h2>Article</h2>
</article>
<footer>
<h2>Footer</h2>
</footer>
A way is using grid:
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: repeat(3, 100px);
grid-gap: 20px;
}
.container div {
background-color: green;
border: solid red 1px;
}
.header {
grid-column: 1 / 6;
}
.main {
grid-column: 1 / 4;
}
.asid {
grid-column: 4 / 5;
}
.article {
grid-column: 5 / 6;
}
.footer {
grid-column: 1 / 6;
}
<div class="container">
<div class="header">header</div>
<div class="main">main</div>
<div class="asid">asid</div>
<div class="article">article</div>
<div class="footer">footer</div>
</div>
I would wrap the .main, .aside, .article blocks with a flex container.
.content {
display: flex;
gap: 10px;
}
.content {
display: flex;
gap: 10px;
}
.header,.main,.aside,.article,.footer{
background-color: lightblue;
border: 3px solid red;
height: 200px;
margin: 1em;
}
.main {
width: 60%;
}
.aside {
width: 20%;
}
.article {
width: 20%;
}
<div class="container">
<div class="header">HEADER</div>
<div class="content">
<div class="main">MAIN</div>
<div class="aside">ASIDE</div>
<div class="article">ARTICLE</div>
</div>
<div class="footer">FOOTER</div>
</div>
Try using flex
section{
display: flex;
}
main, aside, article{
height: 60px;
}
main{
flex-grow: 3;
background: red;
}
aside{
flex-grow: 1;
background: green;
}
article{
flex-grow: 1;
background: blue;
}
<section>
<main>main</main>
<aside>aside</aside>
<article>article</article>
</section>
I would like to fix both the header and the sidebars positioned with css-grids. I tried to use position:fixed but it ends up messing up the interface. Is there a simple way to do this? Or is the only way relative positioning and height/width adjustments? I wouldn't want to make the use of css-grids pointless...
Here's the link to the Codepen if you find it easier (code without lipsum included below): https://codepen.io/fergos2/pen/MWgLqgL?editors=1100
Thanks in advance for helping this newbie!
<div class="container">
<header class="header pd">Header</header>
<div class="left-sidebar pd">
<div class="box-1 pd">
Box-1
</div>
<footer class="footer pd">
Footer
</footer>
</div>
<div class="main-content pd">
Main content
</div>
<div class="right-sidebar pd">
<div class="box-2 pd">
Box-2
</div>
<div class="box-3 pd">
Box-3
</div>
</div>
</div>
.container {
width: 1000px;
margin: 30px auto;
background-color: #eee;
display: grid;
grid-template-rows: min-content 1fr;
grid-template-columns: 1fr 2fr 1fr;
grid-gap: 15px;
grid-template-areas: "head head head"
"leftbar main rightbar";
& > * {
background-color: pink;
color: #ggg;
font-size: 20px;
font-family: sans-serif;
}
}
.pd {
padding: 15px;
}
.header {
grid-area: head;
}
.left-sidebar {
grid-area: leftbar;
display: flex;
flex-direction: column;
justify-content: flex-start;
.box-1 {
color: red;
border: 1px solid purple;
margin-bottom: 5px;
}
.footer {
color: green;
border: 1px solid purple;
}
}
.main-content {
grid-area: main;
}
.right-sidebar {
grid-area: rightbar;
display: flex;
flex-direction: column;
justify-content: flex-start;
.box-2 {
color: red;
border: 1px solid purple;
margin-bottom: 5px;
}
.box-3 {
color: green;
border: 1px solid purple;
}
}
UPDATE:
position: -webkit-sticky;
position: sticky;
top: 0;
seems to work for the header but not for the sidebars (even when setting top:200px for example). Any suggestions on what to do with the sidebars?
Essentially what I need to happen is to set up a grid, but if one of the elements is missing, another element stretches to fill the space.
This is an example Pen of where I'm currently at:
https://codepen.io/Rockster160/pen/JMLaXY
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas: "sidebar header"
"sidebar content"
"sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.footer {
grid-area: footer;
background: orange;
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
footer is an optional element, so when it doesn't exist (commented out as in the code) then content should stretch and line up with the bottom of sidebar.
I've tried a variety of different combinations using min/max content and different auto placements, but no luck. I thought if I had multiple elements named content it might work as well, but no luck there either.
Any help is greatly appreciated!
You are forcing the 3rd row to be 50px in the grid style.
Change it to be adapted to the content, and set the 50px as height in the footer itself:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto max-content; /* changed last 50px to max-content*/
grid-template-areas: "sidebar header"
"sidebar content"
"sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.footer {
grid-area: footer;
background: orange;
height: 50px; /* added */
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
And another posibility, thanks to Michael_B. The sintax of grid-template-rows is clearer:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px 1fr auto;
grid-template-areas: "sidebar header"
"sidebar content"
"sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.footer {
grid-area: footer;
background: orange;
height: 50px; /* added */
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
The easiest way to do this is to use the :last-child selector:
.content:last-child {
grid-row: content / footer;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas: "sidebar header" "sidebar content" "sidebar footer";
margin-bottom: 2rem;
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.content:last-child {
grid-row: content / footer;
}
.footer {
grid-area: footer;
background: orange;
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
Or, alternatively, we could reverse the order of the .content and .footer elements in the HTML (as below) and use the CSS negation operator (:not()) to determine that the .content element should take up extra space if it is not preceded by a .footer element:
:not(.footer) + .content {
grid-row: content/footer;
}
which styles a .content element that is not immediately preceded by a .footer sibling in such a way that it starts in the grid-row identified by content and ends in the grid-row identified by footer:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas: "sidebar header" "sidebar content" "sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
:not(.footer)+.content {
grid-row: content/footer;
}
.footer {
grid-area: footer;
background: orange;
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
References:
grid-row.
:last-child.
Negation pseudo-class:not().
Sometimes things are simpler with flexbox.
Since your container has a defined height (the viewport), you can use flex-flow: column wrap to create both columns.
Then use flex: 1 on the content item, which tells it to consume free space.
When the footer is present, the content makes space for it. When the footer is not present, the content consumes all space.
.grid {
display: flex;
flex-flow: column wrap;
height: 100vh;
background: white;
border: 2px solid red;
}
.sidebar {
flex: 0 0 100%;
width: 250px;
background: green;
}
.header {
flex: 0 0 100px;
width: calc(100% - 250px);
background: lightblue;
}
.content {
flex: 1;
width: calc(100% - 250px);
border: 5px solid black;
background: blue;
}
.footer {
flex: 0 0 50px;
width: calc(100% - 250px);
background: orange;
}
body { margin: 0; }
div { box-sizing: border-box; }
<!-- WITH FOOTER -->
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
<hr>
<!-- WITHOUT FOOTER -->
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
</div>
Change your .grid class to
.grid {
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas:
"sidebar header"
"sidebar content"
"sidebar content";
}
when you comment your footer tag as in your pen, grid is still waiting to have a footer element there, so it's kinda "saving space" for this element there