CSS grid auto in grid-template-areas - css

I have the following CSS:
.card {
display: grid;
grid-template-columns: 1fr 40px;
grid-template-rows: fit-content(10px) fit-content(10px) auto;
grid-template-areas:
"image image"
"description slider"
"details slider";
}
.image-block {
grid-area: image;
}
.description-block {
grid-area: description;
}
.details-block {
grid-area: details;
}
.slider-block {
grid-area: slider;
min-height: 300px;
}
what I am trying to achieve is that my description block only takes up as much space as the content inside of there, and then the details block takes up the rest. This is because the content of the description block is usually smaller than 150 pixels, so I would like the details block to start right under the description block, so it looks nicer.
but what happens is that both these blocks always get the equal amount of space. so if the content of the description block happens to take up only 50 pixels, then it still has 100 pixels of empty space before the details block starts.
is there a way to avoid this?

Related

CSS responsive Grid not responding

I am trying to build a responsive web site with a trivial two-column layout, navigation in the left column followed by content in the next section. The problem is that I haven't yet found the CSS to make the content section drop below the menu on narrow screens.
The menu section is fixed at 15rem - that part works ok.
The main section remains firmly fixed to the right of the menu (causing overflow) no matter what I've tried.
Here's the relevant CSS ...
body {
display: grid;
grid-template-columns: 15rem repeat(auto-fit, minmax(30ch, 1fr)) ;
gap: 0;
margin: auto auto;
}
Here's where the top-level markup (produced in php) is created ...
function sPageContent () {
$sData ='';
$sData.='<!DOCTYPE html>';
$sData.='<HTML lang="en-GB">';
$sData.='<HEAD>'.sDocHead().'</HEAD>';
$sData.='<BODY>';
// $sData.=' <header>'.sPageHeading().'</header>';
$sData.=' <nav>'.sSiteMenu().'</nav>';
$sData.=' <main>'.sContent().'</main>';
// $sData.=' <aside>'.sAnnounce().'</aside>';
// $sData.=' <footer>'.sPageFooter().'</footer>';
$sData.='</BODY>';
$sData.='</HTML>';
return $sData;
}
I can add more detail (or a screen-shot) if required.
You'll notice I've inhibited header/footer in case they were interfering.
I'd be grateful for any insight into what I'm missing.
Thank you.
You'll need a media query to accomplish what you want. Following the principle of mobile-first, the base styles apply in the mobile view and the media-query specifies what happens after the viewport reaches a minimum width.
Run the snippet below and choose the "Full page" option to see how the grid behaves at different sizes.
body {
margin: 0;
min-height: 100vh;
display: grid;
grid-auto-rows: min-content auto min-content;
}
header {
background: skyblue;
}
main {
background: orange;
}
footer {
background: yellowgreen;
grid-column: 1 / -1;
}
#media screen and (min-width: 30em) {
body {
grid-template-columns: 15em 1fr;
grid-auto-rows: auto min-content;
}
}
<header>
<nav>Menu</nav>
</header>
<main>Main Content</main>
<footer>Footer</footer>

How can I force footer on bottom of page on empty/full page with grid layout

I have a few pages with not a lot of content. The whole website is styled with a grid layout - basic header, main and footer:
The goal is to set the footer onto the bottom of the screen with a whitespace from the content, if there isn't a lot going on on the page like this:
For demonstration purposes I used margin-bottom of 50vh on this page.
But if, for example a blog post is bigger than 100vh, the footer should still appear on the bottom - without the whitespace of course:
The user needs to scroll to see the footer on the bottom of the page.
What's a "best practise"-way of achieving this behaviour (preferred without JS(?))?
Some code for those who might want to have a look into the structure of the webpage:
/* inside this class the content is wrapped into the grid layout */
.container {
display: grid;
grid-template-areas:
"header header header header header"
". recent-posts recent-posts recent-posts ."
"footer footer footer footer footer";
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 10px;
}
/* setting header, main and footer as grid layout */
header {
grid-area: header;
border-bottom: 1px solid;
border-radius: 4px;
margin-bottom: 2vh;
}
main {
grid-area: recent-posts;
}
footer {
grid-area: footer;
margin-top: 1vh;
padding: 0.2vh;
border: 1px solid;
border-radius: 4px;
}
If someone wants to have a look into the whole code, I publish the source code on my GitLab.
I got around with a solution which might help someone else in the future:
Inside the .container class I added:
.container {
[…]
/* this forces the footer to stay at the bottom even if the content doesn't fill up the page */
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}
where grid-template-rows equals the amount of rows of the grid layout.
I edited the CSS-file to remove padding around the whole grid-layout which made the page a tiny bit bigger than 100vh and added a scrollbar this way.
Instead I added a margin to the header and footer itself:
footer on low-content pages
footer with more content
On mobile you may need to scroll to see the content due to the URL bar:
landing on mobile startpage
scroll on mobile to see 100vh
I mark this question as solved as this solution does exactly what I want; still, if someone knows a better way, please write an answer!
So this will be how if we use flexbox in this case.
section will act as a container to the whole data except the header and footer. Since the section is defined as flex:1, it will take the entire space except for the header and footer.
In this way, if the content gets overflowed in section, the footer will be pusher further down too. You don't have to worry about any such scenarios.
main {
display: flex;
flex-direction: column;
height: 100vh;
}
header, section, footer {
border: 1px solid #ddd;
padding: 10px;
}
section {
flex: 1;
}
<main>
<header>
Something
</header>
<section class="container">Another thing</section>
<footer>
Footer
</footer>
</main>

Show/hide grid-template-row of empty content or if grid area not rendered

display: grid;
grid-template-columns:var(--side-bar-width) 1fr;
grid-template-rows: 60px 1fr 90px;
gap: 0px 0px;
grid-template-areas:
"Sidebar Header"
"Sidebar Body"
"Player Player";
I have three components, each render a div with a classname of
.Body { ... grid-area: Body; },
.Sidebar { ... grid-area: Sidebar; },
.Player{ ... grid-area: Player; }
respectively
The Player component is a conditional render of height 90px, it is not visible initially so sometimes it looks like the viewport has 90px of empty space at the bottom of the screen at page load
The Player component/content belongs to the Player grid-area. How do you hide the grid-area with empty content dynamically in the grid template? Hiding could mean min-height 0 or display none
In other words, i want to show/hide the last grid-template-row if Player component was rendered then adjust the grid to fill screen
I also saw CSS Grid. Hide unused area & Preventing fixed footer from overlapping content
update:
The Player css has these additional attributes
.Player {
...
height: 90px;
display: flex;
width: 100%;
position: fixed;
bottom: 0;
}
Updated Answer (based on changes to the question)
If the Player grid area must be explicitly defined, then change its row in grid-template-rows to auto or min-content. You can then define the height in the component itself (i.e., height: 90px).
Original Answer
Consider leaving the Player component out of the explicit grid. In other words, don't define it in grid-template-areas or grid-template-rows.
Use grid-auto-rows: 90px.
If necessary, apply grid-row: 3 to the component.
Or even grid-area: 3 / 1 / auto / -1, which is equivalent to:
grid-row-start: 3
grid-column-start: 1
grid-row-end: auto
grid-column-end: -1

Can I have a full height 2nd row taking into account the height of the 1st row in a grid layout?

I have two full width rows. The first one has top and bottom padding so that it has a height. The other must be full height minus the height of the first one.
I used CSS grid layout (even if I have only one column, I don't want to make use of the flexbox layout, for personal reasons):
.main {
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: 100%;
grid-template-areas:
'menu'
'section_1';
}
.menu {
grid-area: menu;
}
.section_1 {
grid-area: section_1;
}
I would want to replace 1fr by something that would allow my second row, named section_1, to be full height minus menu's height without using calc(100vh - <menu_height>). Is it possible? I've tried 1fr but it doesn't work for this purpose of course.
to complete comment untill clarification:
fr means fraction , so you need to set the ratio of fractions of both elements, js will help you here ... but if you don't set any row template it will do without. Can you clarify the use with a snippet with enough code to demonstrate your issue . If you set an height on .main, it will also do the job
are you looking for this :
body {
margin: 0;
}
main {
height: 100vh;/* missing in your code */
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: 100%;
grid-template-areas: 'menu' 'section_1';
}
nav {
grid-area: menu;
}
section {
background: #bee;
grid-area: section_1;
}
<main>
<nav> a nav</nav>
<section> a section </section>
</main>

Is it possible to make grid element take 1.5 space in container?

So I found this layout and I wanted to make it using display: grid
So far I came up with this
.header__grid {
display: grid;
grid-template-columns: 380px 500px 500px;
grid-template-rows: 305px 305px;
grid-template-areas:
"sweets food meat"
"sweets text fruits"
}
.header__grid-sweets {
grid-area: sweets;
}
.header__grid-food {
grid-area: food;
}
.header__grid-meat {
grid-area: meat;
}
.header__grid-text {
grid-area: text
}
.header__grid-fruits {
grid-area: fruits;
}
And it looks like this
The problem is the the last block, with fruits, should take more than one cell in grid and the block to its left should take less. I guess it is because I'm setting with of columns with grid-template-columns
So the question is is there a way to work around this?
All the help will be much appreciated
Instead of this:
grid-template-columns: 380px 500px 500px;
Try something like this:
grid-template-columns: repeat(100, 10px)
Then used line-based placement to created grid areas across those tracks.
Here's an example from another answer.

Resources