CSS Grid: Make nav bar collapsible in mobile - html

Trying my best to learn CSS Grid...
I have made a nav menu but cannot get it to collapse for mobile view ('hamburger' menu style). I have tried using the 'checkbox hack' seen in several videos and online tutorials.
I also can't seem to get all of the links to list (list begins at 'Products' in my mobile view, but should begin at 'About Us').
Been working on this for days with no luck.
If anyone could help me out in getting this to work I would be very grateful.
Here's the HTML & CSS:
html, body{
margin: 0;
padding: 0;
font-family: Roboto, sans-serif;
font-size: 100%;
}
header{
/* grid-column-start: 1;
grid-column-end: 3;
grid-row:1;
*/
grid-area: header;
background-image:linear-gradient(rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.25)), url(../img/rockspiral.jpg);
display: grid;
grid-template-columns: repeat (4, 1fr);
/* 100px, 1fr 1fr 1fr;
*/
/**** Change to 10% and 90% otherwise it takes up the full viewport ****/
grid-template-rows: 100px auto;
grid-template-areas: "logo topbar-nav topbar-nav topbar-nav" ". hero-text hero-text . ";
}
.logo{
grid-area: logo;
background-image:url(../img/logo-mobile.png);
background-repeat: no-repeat;
margin-left: 10px;
}
.topbar-nav{
grid-area: topbar-nav;
color:white;
background-color: lightblue;
justify-self: end;
align-self: center;
}
.topbar-nav, ul, li{
list-style-type: none;
float: left;
padding: 0px 5px 0px 5px;
}
.hero-text{
grid-area: hero-text;
color:white;
justify-self: center;
align-self: center;
}
.hero-text h1{
font-size: 600%;
}
.hero-text p{
font-size: 200%;
text-align: center;
}
nav{
grid-area: nav;
}
.grid-about{
/* grid-column-start: 1;
grid-column-end: 4;
grid-row:2;
*/
grid-area: about;
}
.grid-products{
/* grid-column-start: 1;
grid-column-end: 4;
grid-row:3;
*/
grid-area: products;
}
.grid-services{
/* grid-column-start: 1;
grid-column-end: 4;
grid-row:4;
*/
grid-area: services;
}
.grid-contact{
grid-area: contact;
}
.grid-location{
grid-area: location;
}
.grid-phone-social{
grid-area: phone;
}
footer{
/* grid-column-start: 1;
grid-column-end: 4;
grid-row:6;
*/
grid-area: footer;
}
/****Grid for mobile screens****/
#media (max-width: 767px){
.grid-container{
display: grid;
background-color: aqua;
grid-auto-rows: 50vh;
grid-gap: 10px;
grid-template-areas: "header"
/* "nav"*/
"about" "products" "services" "contact" "location" "phone" "footer";
}
header{
background-image:linear-gradient(rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.25)), url(../img/rockspiral-mobile.jpg);
background-repeat: no-repeat;
/* Change to: grid-template-columns: 110px auto;
*/
grid-template-columns: 110px auto;
grid-template-rows: 50px auto;
grid-template-areas: "logo topbar-nav" "hero-text hero-text";
}
.topbar-nav ul, li{
display: grid;
grid-template-rows: 10px;
grid-gap: 5px;
font-size:75%;
float:left;
}
.hero-text h1{
font-size: 300%;
text-align: center;
}
.hero-text p{
font-size: 150%;
text-align: center;
}
}
/****Grid for tablet screens****/
#media (min-width: 768px){
.grid-container{
display: grid;
grid-auto-rows: 100vh;
grid-gap: 10px;
background-color: red;
grid-template-areas: "header"
/* "nav" */
"about" "products" "services" "contact" "location" "phone" "footer";
}
header{
grid-area: header;
background-image:linear-gradient(rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.25)), url(../img/rockspiral.jpg);
display: grid;
/* changed: column size 260px 1fr 1fr 1fr*/
grid-template-columns: 260px 1fr 1fr 1fr;
grid-template-rows: 100px auto;
grid-template-areas: "logo topbar-nav topbar-nav topbar-nav" "hero-text hero-text hero-text hero-text";
}
.logo{
grid-area: logo;
background-image:url(../img/logo.png);
background-repeat: no-repeat;
margin-left: 10px;
}
}
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/layout.css">
<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">
<title>CSS Grid Sandbox</title>
</head>
<body>
<div class="grid-container">
<header>
<div class="logo"></div>
<div class="topbar-nav">
<ul>
<li>About</li>
<li>Products</li>
<li>Services</li>
<li>Contact</li>
<li>Location & Hours</li>
<li>Phone & Social Media</li>
</ul>
</div>
<div class="hero-text">
<h1>Big Rock Sale</h1>
<p>All rocks 50% off. Offer ends soon!</p>
</div>
</header>
<!-- <nav>Nav</nav> -->
<section class="grid-about">About Us</section>
<section class="grid-products">Products</section>
<section class="grid-services">Services</section>
<section class="grid-contact">Contact</section>
<section class="grid-location">Location & Hours</section>
<section class="grid-phone-social">Phone & Social Media</section>
<footer>Footer</footer>
</div>
</body>
</html>

While I personally recommend using Javascript for this a pure CSS version can be achieved through multiple methods, one of which is by using a checkbox paired with the :checked selector.
.hamburger-menu-content {
display: none;
}
#hamburger-menu-trigger:checked+.hamburger-menu-content {
/* '+' means all elements that have the first element preceding it */
display: block;
}
<input type="checkbox" id="hamburger-menu-trigger">
<div class="hamburger-menu-content">
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
</div>
The downside of this approach is that you need to click the input again to close it.
To mitigate this we could use a pair of radio button.
.hamburger-menu-content {
display: none;
}
#hamburger-menu-trigger:checked {
display: none;
}
#hamburger-menu-trigger:checked+.hamburger-menu-content {
/* '+' means all elements that have the first element preceding it */
display: block;
}
<input type="radio" name="menuToggle" id="hamburger-menu-trigger">
<div class="hamburger-menu-content">
<input type="radio" name="menuToggle">
<p>Foo</p>
<p>Foo</p>
<p>Foo</p>
</div>
edit: In case you want to change the looks of the buttons you can reference this guide https://www.w3schools.com/howto/howto_css_custom_checkbox.asp

Related

how to use css grid to display components at particular area

here's my html code
<div>
<div id="navbar" class="box">Navbar</div>
<div id="sidenav " class="box">Side Navbar</div>
<div id="main " class="box">Main</div>
<div id="footer " class="box">Footer</div>
</div>
and here's my scss code
div{
display: grid;
width:100%;
height: 100%;
grid-template-columns: 25% 75% 25%;
grid-gap: 15px;
grid-template-rows:25% 50% 25% ;
// grid-gap: 15px;
grid-template-areas:
"hd hd hd "
"sd ma ma "
"ft ft ft ";
.box{
display: flex;
// text-align: center;
border: 3px solid red;
/* width:150px;
height: 150px; */
margin: auto;
align-items: center;
justify-content: center;
}
#navbar{
grid-area: hd;
}
#sidenav{
grid-area: sd;
}
#main{
grid-area: ma;
}
#footer{
grid-area: ft;
}
}
the problem is the footer div doesn't display in the bottom here's a screenshot
what i want is to make the footer display at the bottom so what seems to be the problem here
There are some issues that I found in your code which makes the layout little wonky.
grid-template-columns: 25% 75% 25%;
The column total is more than 100%, so it will not work perfectly.
I would highly recommend you to use a CSS grid generator online like https://grid.layoutit.com/
For your layout, I would also not recommend structure 3x3 (columns and rows) - As from the image you shared above it looks like the following
1 row - For "Navbar" (this doesnt need any sub columns)
1 row - For Content -> this has 2 columns 1 for "SideNav" and 1 for "Main"
1 row - For "Footer" (again you dont need sub columns)
Based on this your HTML structure will end up looking like
<div class="container">
<div class="navbar">Navbar</div>
<div class="Content">
<div class="SideNav">Side Nav</div>
<div class="Main">Main</div>
</div>
<div class="Footer">Footer</div>
</div>
And your CSS will look like this
body{
padding: 0;
margin: 0;
}
.container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 25% 50% 25%;
gap: 0px 0px;
grid-template-areas:
"navbar"
"Content"
"Footer";
}
.navbar {
grid-area: navbar;
background-color: #f5f5f5;
padding: 16px;
text-align: center;
}
.Content {
display: grid;
grid-template-columns: 360px 1fr;
grid-template-rows: 1fr;
gap: 0px 0px;
grid-template-areas:
"SideNav Main";
grid-area: Content;
}
.SideNav {
grid-area: SideNav;
background-color: #e5e5e5;
padding: 16px;
}
.Main {
grid-area: Main;
background-color: salmon;
padding: 16px;
}
.Footer {
grid-area: Footer;
background-color: #d5d5d5;
padding: 16px;
text-align: center;
}
Here, if you check the code well, the container has 3 rows (25% - navbar, 50% - content, 25% - footer)
And then content has 2 columns (360px - Sidenav, 1fr - Main)
Hope this helps :)
You can also see the code live on my codepen : https://codepen.io/raunaqpatel/pen/WNyQqmm
Or here:
body{
padding: 0;
margin: 0;
}
.container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 25% 50% 25%;
gap: 0px 0px;
grid-template-areas:
"navbar"
"Content"
"Footer";
}
.navbar {
grid-area: navbar;
background-color: #f5f5f5;
padding: 16px;
text-align: center;
}
.Content {
display: grid;
grid-template-columns: 360px 1fr;
grid-template-rows: 1fr;
gap: 0px 0px;
grid-template-areas:
"SideNav Main";
grid-area: Content;
}
.SideNav {
grid-area: SideNav;
background-color: #e5e5e5;
padding: 16px;
}
.Main {
grid-area: Main;
background-color: salmon;
padding: 16px;
}
.Footer {
grid-area: Footer;
background-color: #d5d5d5;
padding: 16px;
text-align: center;
}
<div class="container">
<div class="navbar">Navbar</div>
<div class="Content">
<div class="SideNav">Side Nav</div>
<div class="Main">Main</div>
</div>
<div class="Footer">Footer</div>
</div>

Blank space at the bottom of my document using CSS grid?

CSS noob here, running into an issue that I can't seem to figure out, my CSS in creating blank space at the bottom of the document, I'd say about 60% of it. Is there something wrong with the parent parameters or the children?
My HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Redacted</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="grid-container">
<ul>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
<li><a id="asides" href="asides.asp">Asides</a></li>
</ul>
<p class="intro">
Bacon Ipsum
</p>
<p class="projects">
Lorem Ipsum
</p>
<footer>Footer placeholder</footer>
</div>
<script src="script.js"></script>
</body>
</html>
CSS:
* {
border: 1px solid gold;
}
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
gap: 10px 10px;
grid-auto-flow: row;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
li {
float: left;
}
a {
display: block;
padding: 8px;
background-color: #ffffff;
}
.intro {
grid-column: 1 / span 4;
grid-row: 2;
}
.projects {
grid-column: 1 / span 4;
grid-row: 3;
}
footer {
grid-column: 1 / span 4;
grid-row: 4;
}
body {
background-color: rgb(124, 252, 188);
margin: 0;
padding: 0;
}
Please excuse the terrible formatting, for now, apologies, and thank you in advance!
You forget to add height on body and grid-container
html,
body {
height: 100%;
}
and add height on the grid-container
.grid-container {
height: 100%;
...
}
CODEPEN
* {
border: 1px solid gold;
}
html,
body {
height: 100%;
}
body {
background-color: rgb(124, 252, 188);
margin: 0;
padding: 0;
}
.grid-container {
height: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
gap: 10px 10px;
grid-auto-flow: row;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
li {
float: left;
}
a {
display: block;
padding: 8px;
background-color: #ffffff;
}
.intro {
grid-column: 1 / span 4;
grid-row: 2;
}
.projects {
grid-column: 1 / span 4;
grid-row: 3;
}
footer {
grid-column: 1 / span 4;
grid-row: 4;
}
<div class="grid-container">
<ul>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
<li><a id="asides" href="asides.asp">Asides</a></li>
</ul>
<p class="intro">
Bacon Ipsum
</p>
<p class="projects">
Lorem Ipsum
</p>
<footer>Footer placeholder</footer>
</div>

Header menu title spacing off in grid

Hope you are all doing great.
I have this code, the header menu sort of work but for some reasons the space between each title is off, I quite tried everything, align-center,self,content , justify-content ... but nothing seems to work, where I am failing ?
I have no idea if it's either Home or Contacts that spacing is completely off
thank you for helping
#import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght#500&display=swap');
body {
margin: 0;
padding: 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
a, u {
text-decoration: none;
}
.wrapper {
min-height: 100vh;
display: grid;
grid-template-columns: repeat(3, auto);
grid-template-rows: auto;
grid-template-areas:
"header"
"main"
"footer";
}
.page-header {
grid-area: header;
height: 12.5vh;
width: 100vw;
background-color: rgb(214, 214, 214);
}
.grid-header {
display: grid;
grid-template-columns: repeat(3, 50px);
grid-template-rows: 2.5em;
display: grid;
justify-content: center;
}
#ph-home {
grid-column: 1/3;
grid-row: 2/3;
}
#ph-blog {
grid-column: 2/3;
grid-row: 2/3;
}
#ph-contacts {
grid-column: 3/3;
grid-row: 2/3;
}
#ph-home>a, #ph-blog>a, #ph-contacts>a {
font-family: 'Ubuntu', sans-serif;
font-size: 120%
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="./css/home.css">
</head>
<body>
<div class="wrapper">
<header class="page-header">
<ul class="grid-header">
<li id="ph-home">
Home
</li>
<li id="ph-blog">
Blog
</li>
<li id="ph-contacts">
Contacts
</li>
</ul>
</header>
</div>
</body>
</html>
You can specify your columns and rows in fractions and force them to take up that percentage of the width of their parents along with grid-template-areas: "#ph-home #ph-blog #ph-contacts" and grid-area on the children. Then add a display: flex on the children of the grid to give them a justify-content property. This will ensure everything is spaced out nicely with no need to add a gap statically in pixels.
On your grid parent:
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: "#ph-home #ph-blog #ph-contacts";
On your grids children:
#ph-home {
display: flex;
justify-content: center;
grid-area: #ph-home;
}
#import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght#500&display=swap');
body {
margin: 0;
padding: 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
a,
u {
text-decoration: none;
}
.wrapper {
min-height: 100vh;
display: grid;
gap: 50px;
grid-template-columns: repeat(3, auto);
grid-template-rows: auto;
grid-template-areas: "header" "main" "footer";
}
.page-header {
grid-area: header;
height: 12.5vh;
width: 100vw;
background-color: rgb(214, 214, 214);
}
.grid-header {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: "#ph-home #ph-blog #ph-contacts";
}
#ph-home {
display: flex;
justify-content: center;
grid-area: #ph-home;
}
#ph-blog {
display: flex;
justify-content: center;
grid-area: #ph-blog;
}
#ph-contacts {
display: flex;
justify-content: center;
grid-area: #ph-contacts;
}
#ph-home>a,
#ph-blog>a,
#ph-contacts>a {
font-family: 'Ubuntu', sans-serif;
font-size: 120%
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="./css/home.css">
</head>
<body>
<div class="wrapper">
<header class="page-header">
<ul class="grid-header">
<li id="ph-home">
Home
</li>
<li id="ph-blog">
Blog
</li>
<li id="ph-contacts">
Contacts
</li>
</ul>
</header>
</div>
</body>
</html>
Try this in the 'header'
display:flex;
justify-content: center;

CSS-grid: automatic placement within a named column (centered layout with full-width elements)

I created a layout with grid-css that contains 12 columns in the center with a maximum-width and 2 columns which will only be shown on large screens. This technique is based on the following article. (In the example the max-width is set to a small number, to make it easier to examine)
The problem I want to solve is:
I want to use classes to determine how many columns wide an element should be. Like you can see in the example below, I have a class col-10 and col-6. Similar to the bootstrap framework.
Is there some way I can say that the element with a class "col" for example, should be always inside the main column and ignore the outer columns which are included in the full column?
At the moment the only solution I found was giving the first element in a row, the correct starting point. (In the example it is the class "main-start")
Example code:
*{
margin: 0;
padding: 0;
font-family: sans-serif;
}
nav{
display:flex;
justify-content: flex-end;
}
a{
text-decoration:none;
color:white;
font-size: 10px;
background-color: orange;
padding: 0.5em;
}
.grid{
display: grid;
grid-template-columns:
[full-start]minmax(0, 1fr)
[main-start] repeat(12, minmax(0, 40px)) [main-end]
minmax(0, 1fr)
[full-end];
}
.main-start{
grid-column-start: main-start;
}
.col-6{
grid-column-end: span 6;
}
.col-10{
grid-column-end: span 10;
}
.full-width{
grid-column:full;
}
.gradient{
color: white;
text-align:center;
height: 90px;
background:linear-gradient(to bottom right, red,coral);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=">
<title>Grid centered design with full width elements</title>
</head>
<body>
<header class="grid">
<h1 class="col-6 main-start">MyWebsiteTitle</h1>
<nav class="col-6">
Page1
Page2
Page3
</nav>
<p class="col-10">This is not inside main because it has no main-start class</p>
<div class="full-width gradient">A full-width banner</div>
</header>
</body>
</html>
An idea is to consider an empty element that will fill the first column which will force all the element to start where you want:
* {
margin: 0;
}
nav {
display: flex;
justify-content: flex-end;
}
.grid {
display: grid;
grid-template-columns:
[full-start]minmax(0, 1fr)
[main-start] repeat(12, minmax(0, 40px)) [main-end] minmax(0, 1fr) [full-end];
}
/* added */
.grid::before {
content:"";
grid-column:full-start/main-start;
grid-row:span 100; /* take a lot of rows */
}
/**/
.col-6 {
grid-column-end: span 6;
}
.col-10 {
grid-column-end: span 10;
}
.full-width {
grid-column: full;
}
.gradient {
color: white;
text-align: center;
height: 90px;
background: linear-gradient(to bottom right, red, coral);
}
<header class="grid">
<h1 class="col-6">MyWebsiteTitle</h1>
<nav class="col-6">
Page1
Page2
Page3
</nav>
<p class="col-10">This is not inside main because it has no main-start class</p>
<div class="full-width gradient">A full-width banner</div>
</header>
As a response to the problem with the row-gap with the previous answer. Here is an example where the row-gap is replaced with a margin:
*{
margin: 0;
padding: 0;
font-family: sans-serif;
}
nav{
display:flex;
justify-content: flex-end;
}
a{
text-decoration:none;
color:white;
font-size: 10px;
background-color: orange;
padding: 0.5em;
}
.grid{
display: grid;
/* added */
column-gap: 0.5rem;
/**/
grid-template-columns:
[full-start]minmax(0, 1fr)
[main-start] repeat(12, minmax(0, 40px)) [main-end]
minmax(0, 1fr)
[full-end];
}
/* added */
.grid::before {
content:"";
grid-column:full-start/main-start;
grid-row:span 100; /* take a lot of rows */
}
.grid > *:not(:last-child) {
/* row-gap */
margin-bottom: 0.5rem;
}
/**/
.main-start{
grid-column-start: main-start;
}
.col-6{
grid-column-end: span 6;
}
.col-10{
grid-column-end: span 10;
}
.full-width{
grid-column:full;
}
.gradient{
color: white;
text-align:center;
height: 90px;
background:linear-gradient(to bottom right, red,coral);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=">
<title>Grid centered design with full width elements</title>
</head>
<body>
<header class="grid">
<h1 class="col-6 main-start">MyWebsiteTitle</h1>
<nav class="col-6">
Page1
Page2
Page3
</nav>
<p class="col-10">This is not inside main because it has no main-start class</p>
<div class="full-width gradient">A full-width banner</div>
</header>
</body>
</html>

CSS Grid hiding text on mobile (mobile first)

I am building a navigation bar and using CSS grid.
Here is the html:
<nav class="nav">
<div class="menu">
<div class="header">
HEADER
</div>
</div>
<span class="space"></span>
<div class="breadcrumb">
<div class="bcrumb">
Breadcrumbs
</div>
</div>
</nav>
<div class="content">
</div>
And here is my CSS:
body {
font-family: sans-serif;
margin:0;
}
.nav {
height: 100px;
position: fixed;
right: 0;
left: 0;
top: 0;
display:grid;
grid-template-rows: 1fr 5px 1fr;
grid-template-areas:
"Menu"
"Space"
"Breadcrumb"
}
.content{
height:1000px;
background-color:gray;
margin-top:100px;
}
.menu {
grid-area: Menu;
background-color: #333333;
display: grid;
grid-template-columns: 1.5em 80px 1fr auto;
grid-template-areas: ". . . MenuItems";
}
.menu-items {
grid-area: MenuItems;
}
.space {
grid-area: Space;
background-color: #c20418;
}
.breadcrumb {
grid-area: Breadcrumb;
background-color: white;
}
#media only screen and (min-width : 1224px) {
.menu {
display:inline-grid;
grid-template-columns: 1.5em 80px auto 1fr auto auto;
grid-template-areas: ". . Header . . MenuItems";
align-content: end;
}
.header {
grid-area: Header;
color: white;
font-size: 1.2em;
}
.breadcrumb {
display: grid;
grid-template-columns: 1.5em 80px 1fr;
grid-template-areas: ". . Bcrumb";
}
.bcrumb {
grid-area: Bcrumb;
align-self: center;
font-size: 1.2em;
}
}
I have made it with an header text and text place for breadcrumbs that should only be there when on larger screens.
I've made it work by adding:
.header, .bcrumb{
visibility:hidden;
}
and then set it to visible in the media queries.
But surely there must be a better way to do this?
Here is a Fiddle with the same code.
Here is the CSS for mobile screens
#media all and (max-width: 767px) {
.header, .bcrumb {
visibility: hidden;
}
}