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>
Related
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>
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?
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>
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.
I have a div that is a css grid container. When the page width drops below a certain size, I would like all elements of the grid to be placed on a line. I think you should be able to change the display type to flex box, I tried doing this and the grid stays the same. Here is the code I am using:
See the Pen NYjOmL by biltimi#gmail.com (#MeaningOf42) on CodePen.
/* The important part of the CSS*/
#media (max-width: 40em) {
.image {
visibility:hidden;
}
.grid-container {
display: inline-flex;
}
}
/* The Styling of the container class: */
.grid-container {
display: grid;
width: 75%;
margin: auto;
padding: 10px;
height: 100px;
grid-template-columns: 16.6% 16.6% 33% 16% 16%;
grid-template-rows: 2fr 3fr 3fr 1fr;
grid-template-areas:
". . Image . ."
"blog bikes Image about links"
"shop events Image contact team"
". . Image . ."
}
For context, I am trying to replicate deaf pigeon's website ( http://www.deafpigeon.co.uk) using as close to pure vanilla HTML and CSS to practice laying out pages. I want my div to do the same thing as the deaf pigeon navigation bar.
Does anyone have solutions? I might be going about this the wrong way if so be sure to let me know.
As Pete said, your media query needs to follow your base rules in order to override when the condition is met. The preferred approach would be to declare your mobile styles first followed by a desktop override in your media query.
.grid-container {
display: inline-flex;
}
#media all and (min-width: 40em) {
.grid-container {
display: grid;
}
}
Notice the change from max-width to min-width to ensure that this override kicks in when the viewport is larger than 40em
Just move your media query declaration to the end of the file. The media query rule you defined is getting executed but it is getting overwritten by the .grid-container rule that comes after it.