I am new to CSS and HTML and have a setup of divs in CSS, something like this:
#topBar {
margin-top: 0;
height: 100px;
width: 100%
}
#sideBar {
width: 50px;
margin-left: 0;
margin-top: 100px;
height: 100%;
}
#main {
margin-left: 50px;
margin-top: 100px;
margin-bottom: 50px;
}
#footer {
margin-bottom: 0;
width: 100%;
}
<div id="container">
<div id="topbar" />
<div id="sidebar" />
<div id="main" />
<div id="footer" />
</div>
But that does not look anything like how I want it. It leaves space for every div, even though their space is restricted to x width and x height.
How could I set up divs to look as desired? Ie have a footer, main, sidebar, and topbar in CSS?
CSS actually has built in grid "builder" that you can use. I was doing something similar not long ago and ended up doing it like this:
#container {
display: grid; //uses grid
height: 100vh; // vh and vw is percentages of the screens width and height, nice for scaling for different devices
width: 100vw;
grid-template-columns: 1fr 9fr; // sets how big columns are, this sets the column quantity to two, and the first one gets 1 fraction of the are, and column two gets 9 fractions. 1fr is for sidebar
grid-template-rows: 1.5fr 15fr 3fr; // Same as with column, but this includes footer, so 1.5 fraction goes to top bar, 15 fractions to sidebar and main area, and 3 fractions to footer
grid-template-areas:
"header header" // sets area to use, the same area given space in above lines. They can be directly referenced in other parts of the css documents.
"navbar main"
"footer footer";
}
#topbar {
grid-area: header; // Referencing previous made areas
display: flex; // I used this to make the top bar, as this would align the items in the bar horizontally with same amount of space between
justify-content: space-between;
align-items: center; //used this to center items vertically
}
#sidebar {
grid-area: sidebar;
text-align: center; // used this to align the text center horizontally
}
#main {
grid-area: main;
}
#footer {
grid-area: footer;
}
You should use the semantic tags such as the header, nav, aside, footer and main.
Then apply the grid directly to the body element instead of wrapping them in an extra container:
body {
margin: 0; /* removes default margin */
display: grid; /* uses grid */
min-height: 100vh; /* will expend the grid to the entire viewport */
grid-template-columns: 1fr 2fr; /* sets the column width and amount */
grid-template-rows: min-content auto min-content; /* sets the row height to push the footer at the bottom and let the main fill the rest */
gap: 5px; /* placing the items apart */
}
header,
footer {
grid-column: 1 / -1; /* letting those element span the entire row */
}
/* for styling purpose only */
header,
aside,
main,
footer {
border: 2px dashed red;
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
}
<header>Topbar</header>
<aside>Sidebar</aside>
<main>Main</main>
<footer>Footer</footer>
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 am trying to achieve this layout by using CSS grid.
Picture:
This is what I have so far:
#wrapper {
display: grid;
gap: 20px;
grid-template-columns: auto 300px 1fr 1fr 180px auto;
grid-template-rows: auto;
grid-template-areas:
"logo nav-primary nav-primary nav-primary nav-primary search"
"nav-secondary nav-secondary nav-secondary nav-secondary nav-secondary nav-secondary"
"aside-1 aside-1 article article aside-2 aside-2"
"footer footer footer footer footer footer";
}
/* Article: use up remaining width */
#article{
grid-area: article;
}
/* Logo: use up a little width as possible */
#logo{
grid-area: logo;
}
/* Nav Primary: use up remaining width */
#nav-primary{
grid-area: nav-primary;
}
/* Nav Secondary: use full width */
#nav-secondary{
grid-area: nav-secondary;
}
/* Search: use up a little width as possible */
#search{
grid-area: search;
}
/* Aside 1: fixed with of 300px */
#aside-1{
grid-area: aside-1;
}
/* Aside 2: fixed with of 180px */
#aside-2{
grid-area: aside-2;
}
/* Footer: use full width */
#footer{
grid-area: footer;
}
/* Demo style */
#wrapper > * {
background: #C4C4C4;
padding: 10px;
}
<div id="wrapper">
<article id="article">Article (use up remaining space)</article>
<header id="logo">Logo</header>
<nav id="nav-primary">Nav Primary</nav>
<nav id="nav-secondary">Nav Secondary</nav>
<form id="search">Search Form</form>
<aside id="aside-1">Aside 1 (fixed width: 300px)</aside>
<aside id="aside-2">Aside 2 (fixed width: 180px)</aside>
<footer id="footer">Footer</footer>
</div>
Codepen: https://codepen.io/aobrien/pen/YzwNZpy
The issue is that Aside1 is not 300px, but instead 300px + the width of the logo column. Same for Aside2, its 180px + the width of the search column.
I can’t seem to set a fixed width for Aside1 and Aside2, while at the same time having the logo and the search be dynamic in width to fit their content and be as small as possible.
The logo box must always be as small as possible so it only fits the content. Same for the search, as small as possible.
Aside1 needs to have a fixed width of 300px and Aside2 needs to have a fixed width of 180px.
My only rule is, I cannot make any changes to the HTML structure as seen, so no nesting of these items. However I can add new HTML elements inside of the current elements, which could contain a fixed width (if that helps?).
I don’t have to rely on grid-template-areas, it can be an explicit or implicit grid. It can also contain more columns if it somehow helps. Any changes to the CSS are welcome.
The only solution I seem to have had so far (which is not a solution I want to settle for) is to assign a fixed width to the logo and the search and then calculate the remaining width to achieve the width of Aside1 and Aside2. However this is really not what I was looking for as I would like to keep it as dynamic as possible without the need to manually set multiple fixed widths across the layout.
Another solution I tried was instead of defining a fixed width of Aside1 via grid-template-columns, I could create a new div inside of Aside1 and give that a width: 300px and set grid-template-columns to auto for that column. This does work except if the logo gets wider than 300px then Aside1 becomes wider than 300px as well.
Does anyone have any solutions or pointers that could help me out?
First of all you have 6 columns, but we can keep only 5 for this task. Second - we don't need to set fixed width in grid-template-columns if we are going to use t cells collapsing. Match easier to set fixed width for specific columns. Here you go
#wrapper {
display: grid;
gap: 15px;
grid-template-columns: auto auto 1fr auto auto;
grid-template-rows: auto;
grid-template-areas:
"logo nav-primary nav-primary nav-primary search"
"nav-secondary nav-secondary nav-secondary nav-secondary nav-secondary"
"aside-1 aside-1 article aside-2 aside-2"
"footer footer footer footer footer";
}
/* Article: use up remaining width */
#article {
grid-area: article;
}
/* Logo: use up a little width as possible */
#logo {
grid-area: logo;
max-width: 300px;
}
/* Nav Primary: use up remaining width */
#nav-primary {
grid-area: nav-primary;
}
/* Nav Secondary: use full width */
#nav-secondary {
grid-area: nav-secondary;
}
/* Search: use up a little width as possible */
#search {
grid-area: search;
max-width: 180px;
}
/* Aside 1: fixed with of 300px */
#aside-1 {
grid-area: aside-1;
width: 300px;
}
/* Aside 2: fixed with of 180px */
#aside-2 {
grid-area: aside-2;
width: 180px;
}
/* Footer: use full width */
#footer {
grid-area: footer;
}
/* Demo style */
#wrapper>* {
background: #C4C4C4;
padding: 10px;
box-sizing: border-box;
}
<div id="wrapper">
<article id="article">Article (use up remaining space)</article>
<header id="logo">Logo</header>
<nav id="nav-primary">Nav Primary</nav>
<nav id="nav-secondary">Nav Secondary</nav>
<form id="search">Search Form</form>
<aside id="aside-1">Aside 1 (fixed width: 300px)</aside>
<aside id="aside-2">Aside 2 (fixed width: 180px)</aside>
<footer id="footer">Footer</footer>
</div>
Note that in this case your Logo should be less than 300px width. And Search should be less than 180px width. If you want Search to be wider than 180px - we should edit the code a bit.
#wrapper {
display: grid;
gap: 15px;
grid-template-columns: auto auto 1fr auto auto auto;
grid-template-rows: auto;
grid-template-areas:
"logo nav-primary nav-primary search search search"
"nav-secondary nav-secondary nav-secondary nav-secondary nav-secondary nav-secondary"
"aside-1 aside-1 article article aside-2 aside-2"
"footer footer footer footer footer footer";
}
/* Article: use up remaining width */
#article {
grid-area: article;
}
/* Logo: use up a little width as possible */
#logo {
grid-area: logo;
max-width: 300px;
}
/* Nav Primary: use up remaining width */
#nav-primary {
grid-area: nav-primary;
}
/* Nav Secondary: use full width */
#nav-secondary {
grid-area: nav-secondary;
}
/* Search: use up a little width as possible */
#search {
grid-area: search;
}
/* Aside 1: fixed with of 300px */
#aside-1 {
grid-area: aside-1;
width: 300px;
}
/* Aside 2: fixed with of 180px */
#aside-2 {
grid-area: aside-2;
width: 180px;
}
/* Footer: use full width */
#footer {
grid-area: footer;
}
/* Demo style */
#wrapper>* {
background: #C4C4C4;
padding: 10px;
box-sizing: border-box;
}
<div id="wrapper">
<article id="article">Article (use up remaining space)</article>
<header id="logo">Logo</header>
<nav id="nav-primary">Nav Primary</nav>
<nav id="nav-secondary">Nav Secondary</nav>
<form id="search">Search Form</form>
<aside id="aside-1">Aside 1 (fixed width: 300px)</aside>
<aside id="aside-2">Aside 2 (fixed width: 180px)</aside>
<footer id="footer">Footer</footer>
</div>
So I am creating a layout where I have a
<div id="structure-content">
<main>content goes here</main>
<aside>aside content</aside>
</div>
I want the aside to be a quarter of the width and to automatically wrap to below the main once it hits a certain size and the main to take the full width. I know I can do this with media queries but people are saying that it can be done with grid and no media queries. I have been experimenting and researching for hours and cannot work it out. Any ideas? If it cannot be done then that is fine and I can try it with flexbox or media queries.
Props in advance.
The below code the div reach certain size will goes down automatically. If you want to drop the div particular size we have to use media query only.
#structure-content {
margin-bottom: 1em;
background: #fff;
color: #fff;
padding: 1.5em 1em;
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
main {
background: green;
}
aside {
background: blue;
}
main,
aside {
flex: 1 0 15em;
margin-left: 0.5em;
margin-right: 0.5em;
}
<div id="structure-content">
<main>content goes here</main>
<aside>aside content</aside>
</div>
With CSS Grid, you can make the main and aside to take half of the available width and auto-wrap when either of the grid item hit a minimum width using grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) - see demo below:
body {
margin: 0;
}
#structure-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
main {
background: aliceblue;
}
aside {
background: cadetblue;
}
<div id="structure-content">
<main>content goes here</main>
<aside>aside content</aside>
</div>
Solution
With CSS Grid, I'd say you can go with media queries. Anyway a flexbox will work here nice:
use a wrapping flexbox
keep a min-width for each of aside and main and add flex: 1 to flex it to the remaining space if available - see demo below:
body {
margin: 0;
}
#structure-content {
display: flex;
flex-wrap: wrap; /* a wrapping flexbox */
}
main {
background: aliceblue;
min-width: 75vw; /* forces aside to take one-fourth space */
flex: 1;
}
aside {
background: cadetblue;
min-width: 250px; /* minimum width of aside */
flex: 1;
}
<div id="structure-content">
<main>content goes here</main>
<aside>aside content</aside>
</div>
I'm using the following grid layout:
grid-template-columns: 10em 1fr 10em;
grid-template-rows: 2em 1fr 2em;
To create a centered area that fills most of the screen while leaving some padding around it. Inside this 1fr x 1fr grid area is a pane div which contains an editor div which contains a content div.
The content div can be any height, and the editor div has overflow: scroll set. My problem is that instead of pane staying the same size and editor handling the overflow, pane grows and causes the whole page to scroll.
I can keep pane from growing by setting its overflow: scroll, but this causes the editor itself to scroll, rather than its content. This is unacceptable because the editor has buttons which must always be on screen.
Is there a way, within grid layout, to allow this functionality? I originally had it working with a flex layout, where the pane div was a single item within a 100% x 100% flexbox. I switched to grid to allow me to easily resize side-menus, so implementing this without grid is not preferable.
Also, multi-browser support would be amazing, but my target browser is Chrome.
Here's a jsfiddle with my reproducing my problem.
body, html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#site {
width: 100%;
height: 100%;
background-color: #000;
display: grid;
grid-template-rows: 10em 1fr 10em;
grid-template-columns: 2em 1fr 2em;
grid-template-areas:
'top top top'
'lpn mid rpn'
'bot bot bot';
}
#pane {
grid-area: mid;
height: 100%;
width: 100%;
background-color: #f0f;
}
#editor {
display: relative;
overflow: scroll;
}
#content {
height: 2000px;
}
<div id='site'>
<div id='pane'>
<div id='editor'>
<div id='content'>
</div>
</div>
</div>
</div>
min-width: auto / min-height: auto
Generally speaking, a grid item cannot be smaller than its content. The default minimum size of grid items is min-width: auto and min-height: auto.
This often causes grid items to overflow their grid areas or grid containers. It also prevents scrollbars from rendering on the items, since an overflow condition can't be triggered (the grid item just keeps expanding).
To override this default (and allow grid items to shrink past their content size) you can use min-width: 0, min-height: 0 or overflow with any value other than visible.
This behavior, with references to official documentation, is explained in this post:
Prevent content from expanding grid items
1fr
Another thing to note is that 1fr means minmax(auto, 1fr). This means, again, that the track to which it is applied cannot shrink below the content size (i.e., the min value in the minmax() function is auto, meaning content-based).
Therefore, to override this setting, use minmax(0, 1fr) instead of 1fr.
More details here: https://github.com/w3c/csswg-drafts/issues/1777
revised demo (tested in Chrome, Firefox and Edge)
body, html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#site {
width: 100%;
height: 100%;
background-color: #000;
display: grid;
/* grid-template-rows: 10em 1fr 10em; */
grid-template-rows: 10em minmax(0, 1fr) 10em; /* new */
grid-template-columns: 2em 1fr 2em;
grid-template-areas:
'top top top'
'lpn mid rpn'
'bot bot bot';
}
#pane {
grid-area: mid;
height: 100%;
width: 100%;
background-color: #f0f;
overflow: auto; /* new */
}
#editor {
/* display: relative; */
/* overflow: scroll; */
}
#content {
height: 2000px;
}
<div id='site'>
<div id='pane'>
<div id='editor'>
<div id='content'></div>
</div>
</div>
</div>
jsFiddle demo
Not 100% sure if this is what you're asking. I added a wrapper to content to make it scrollable, and set a vh height on it, which you could adjust.
#content-scroll {
height: 40vh;
overflow: scroll;
}
#content {
height: 2000px;
}
<div id='site'>
<div id='pane'>
<div id='editor'>
<div id='content-scroll'>
<div id='content'>
</div>
</div>
</div>
</div>
</div>
https://jsfiddle.net/16owL8x0/
I'm trying to build a layout with CSS Grid. I want the header element to be 'sticky'. That is, when the user scrolls, the header stays fixed to top of viewport and other content scrolls up and underneath header. I'd like to give this header a background image.
I've assigned a background image to the header, given it a position value of fixed and applied a z-index value of 999. Other elements below have been positioned and given lower z-index values.
My problem is that this setup doesn't work. I tried a few variations on the CSS but the background image either completely disappears or, on scroll, the header does not stay above other elements as they move up the screen.
What am I doing wrong? I browsed other questions in this forum and also on the web in general but can't find an answer.
Any suggestions much appreciated.
My code is shown below (including various changes to CSS - commented out in most cases).
body {
display: grid;
grid-template-areas: "header header header" "nav article ads" "footer footer footer";
grid-template-rows: 250px 900px 70px;
grid-template-columns: 20% 1fr 15%;
grid-row-gap: 10px;
grid-column-gap: 10px;
height: 100vh;
margin: 0;
}
header {
/* position:fixed;
z-index:999;*/
}
footer, article, nav, div {
padding: 1.2em;
background: gold;
}
#pageHeader {
grid-area: header;
padding: 1.2em;
background: url(https://placeimg.com/50/250/arch) left top repeat-x fixed;
}
#pageFooter {
grid-area: footer;
}
#mainArticle {
grid-area: article;
position: relative;
z-index: 9;
}
#mainNav {
grid-area: nav;
position: relative;
z-index: 8;
}
#siteAds {
grid-area: ads;
position: relative;
z-index: 7;
}
/* Stack the layout on small devices. */
#media all and (max-width: 575px) {
body {
grid-template-areas: "header" "article" "ads" "nav" "footer";
grid-template-rows: 80px 1fr 70px 1fr 70px;
grid-template-columns: 1fr;
}
}
<body>
<header id="pageHeader">Header</header>
<article id="mainArticle">Article</article>
<nav id="mainNav">Nav</nav>
<div id="siteAds">Ads</div>
<footer id="pageFooter">Footer</footer>
</body>
Remove other elements z-index. add position: fixed on your header and give it a width and height then also z-index of 1
Element positioned absolute works kinda like layers. The DOM and z-index (x and y axis is 2d coords and z axis is for the stacking) tells it where to sit depending on where it is on the DOM.
Read through this for a detailed explination...I will most likely screw it up if I try explain any further.
Your <header> element needs to be placed outside of your grid. Currently, the grid encompasses everything, including the header, since it's on the body tag. Instead of using display: grid; on the body, make a container within the body that has display: grid;, and make the header live outside of that container. For example:
HTML:
<body>
<header>Header content!</header>
<div class="container">
<div class="mainNav"></div>
<div class="sidebar"></div>
<div class="siteAds"></div>
<!-- etc. -->
</div>
</body>
And the CSS:
body {
/* your normal body styles go here */
/* but display: grid; should no longer be here */
}
header {
position: fixed;
z-index: 10;
height: 100px;
}
.container {
display: grid;
margin-top: 100px; /* to offset the header's height */
/* and all the rest of your grid styles */
}
What's important to remember here is that the header must not be part of the grid layout.
Use this Jsfiddle...
I have added some css styles and jQuery
CSS
#pageHeader.fixed {
position: fixed;
top:0;
left:0;
width: 100%;
z-index: 99;
}
jQuery
$(window).scroll(function(){
var sticky = $('#pageHeader'),
scroll = $(window).scrollTop();
if (scroll >= $('#pageHeader').height()){
sticky.addClass('fixed');
$('#pageHeader').addClass('fixed');
} else {
sticky.removeClass('fixed');
$('#pageHeader').removeClass('fixed');
}
});