I have an SPA where the main view is a header, navbar and responsive content in the main
body of the HTML.
The content comprises one or more <article>
s (I've swapped these to <div>
s and it's made no difference) which,
when they have a decent amount of content (~100 characters or more) the articles correctly display left to right
and respond to the screen resizing.
But when they only have a small amount of content they become right justified.
Not working - right justified (small content in each article):
Working correctly - left justified (larger content in each article):
Here's a cut down version of the HTML and CSS that replicates the problem (I've removed the side navbar, which makes no difference to the behaviour.
These examples show the problem - fill in the <p>...</p>
content with lorum ipsum text to
see the problem go away.
:root{
--base-clr: #11121a;
--header-clr: #8a918c;
--header-text-clr: #2d302e;
--line-clr: #42434a;
--hover-clr: #222533;
--text-clr: #e6e6ef;
--accent-clr: #5e63ff;
--secondary-text-clr: #b0b3c1;
--header-bar-height: 40px;
}
*{
margin: 0;
padding: 0;
}
html{
font-family: Poppins, 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.5rem;
}
body{
min-height: 100vh;
min-height: 100dvh;
background-color: var(--base-clr);
color: var(--text-clr);
}
#spa {
display: grid;
grid-template-areas:
"header navbar content";
grid-auto-flow: column;
grid-template-columns: auto 1fr;
}
main{
grid-area: content;
padding: min(30px, 7%);
min-height: calc(100vh - var(--header-bar-height));
}
main p{
color: var(--secondary-text-clr);
margin-top: 5px;
margin-bottom: 15px;
}
article{
border: 1px solid var(--line-clr);
box-shadow: 2px 2px 6px 0px rgba(0, 0, 0, 0.3);
border-radius: 1em;
margin-bottom: 20px;
padding: min(3em, 15%);
h2, p { margin-top: 1em }
}
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>GridCss</title>
<link href="./app.css" rel="stylesheet"/>
</head>
<body>
<div id="app">
<div id="spa">
<header>
Header
</header>
<main>
<div class="grid">
<article>
<img src="https://www.mig-welding.co.uk/forum/data/avatars/s/40/40757.jpg" alt="Sample photo">
<div class="text">
<h3>Seamlessly visualize quality</h3>
<p>small text</p>
<button>Here's why</button>
</div>
</article>
<article>
<img src="https://www.mig-welding.co.uk/forum/data/avatars/s/40/40757.jpg" alt="Sample photo">
<div class="text">
<h3> Seamlessly visualize quality</h3>
<p>tiny</p>
<button>Here's why</button>
</div>
</article>
</div>
</main>
</div>
</div>
</body>
</html>
Edit:
The solution from @pr0f3ss0r has addressed this main question, but there's now a secondary issue. They recommended removing the outer <spa>
wrapper and CSS but, without that, the page is propagating a display: block;
to the <main>
code, which has the effect of pushing the content below the side bar.
Here's what it looks like without the <spa>
wrapper and CSS:
I can half-fix this, by reintroducing a wrapper and setting its display: grid;
...
This is why I thought the grid needed to be on an outer object, because it had to set positions of three pieces of content; header, navbar and main
Edit2: Second code snippet added
Original issue of right alignment fixed, but main content appears below the 100vh
viewport window.
:root{
--base-clr: #11121a;
--header-clr: #8a918c;
--header-text-clr: #2d302e;
--line-clr: #42434a;
--hover-clr: #222533;
--text-clr: #e6e6ef;
--accent-clr: #5e63ff;
--secondary-text-clr: #b0b3c1;
--header-bar-height: 40px;
}
*{
margin: 0;
padding: 0;
}
html{
font-family: Poppins, 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.5rem;
}
body{
min-height: 100vh;
min-height: 100dvh;
background-color: var(--base-clr);
color: var(--text-clr);
}
.grid{
display: grid;
grid-template-areas: "header navbar content";
}
header{
grid-area: header;
height: var(--header-bar-height);
width: 100%;
border-right: none;
border-top: 1px solid var(--line-clr);
padding: 0;
margin-bottom: 3px;
position: fixed;
top: 0;
background-color: var(--header-clr);
color: var(--header-text-clr);
}
main{
grid-template-columns: auto 1fr;
display:flex;
grid-area: content;
padding: min(30px, 7%);
box-sizing:border-box;
}
main p{
color: var(--secondary-text-clr);
margin-top: 5px;
margin-bottom: 15px;
}
article{
border: 1px solid var(--line-clr);
box-shadow: 2px 2px 6px 0px rgba(0, 0, 0, 0.3);
border-radius: 1em;
margin-bottom: 20px;
padding: min(3em, 15%);
h2, p { margin-top: 1em }
}
#sidebar{
grid-area: navbar;
box-sizing: border-box;
height: calc(100vh - var(--header-bar-height));
width: 250px;
padding: 5px 1em;
background-color: var(--base-clr);
border-right: 1px solid var(--line-clr);
position: sticky;
top: var(--header-bar-height);
align-self: start;
transition: 300ms ease-in-out;
overflow: hidden;
text-wrap: nowrap;
}
#sidebar.close{
padding: 5px;
width: 60px;
}
#sidebar ul{
list-style: none;
}
#sidebar > ul > li:first-child{
display: flex;
justify-content: flex-end;
margin-bottom: 16px;
.logo{
font-weight: 600;
}
}
#sidebar ul li.active a{
color: var(--accent-clr);
svg{
fill: var(--accent-clr);
}
}
#sidebar a, #sidebar .nav-dropdown-btn, #sidebar .logo{
border-radius: .5em;
padding: .85em;
text-decoration: none;
color: var(--text-clr);
display: flex;
align-items: center;
gap: 1em;
}
.nav-dropdown-btn{
width: 100%;
text-align: left;
background: none;
border: none;
font: inherit;
cursor: pointer;
}
#sidebar svg{
flex-shrink: 0;
fill: var(--text-clr);
}
#sidebar a span, #sidebar .nav-dropdown-btn span{
flex-grow: 1;
}
#sidebar a:hover, #sidebar .nav-dropdown-btn:hover{
background-color: var(--hover-clr);
}
#sidebar .sub-menu{
display: grid;
grid-template-rows: 0fr;
transition: 300ms ease-in-out;
> div{
overflow: hidden;
}
}
#sidebar .sub-menu.show{
grid-template-rows: 1fr;
}
.nav-dropdown-btn svg{
transition: 200ms ease;
}
.rotate svg:last-child{
rotate: 180deg;
}
#sidebar .sub-menu a{
padding-left: 2em;
}
#sidebar-toggle-btn{
margin-left: auto;
padding: 1em;
border: none;
border-radius: .5em;
background: none;
cursor: pointer;
svg{
transition: rotate 150ms ease;
}
}
#sidebar-toggle-btn:hover{
background-color: var(--hover-clr);
}
<header>
Header
</header>
<nav id="sidebar">
<ul>
<li>
<span class="logo">coding2go</span>
<button onclick=toggleSidebar() id="sidebar-toggle-btn">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
fill="#e8eaed">
<path
d="m313-480 155 156q11 11 11.5 27.5T468-268q-11 11-28 11t-28-11L228-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 27.5-11.5T468-692q11 11 11 28t-11 28L313-480Zm264 0 155 156q11 11 11.5 27.5T732-268q-11 11-28 11t-28-11L492-452q-6-6-8.5-13t-2.5-15q0-8 2.5-15t8.5-13l184-184q11-11 27.5-11.5T732-692q11 11 11 28t-11 28L577-480Z"/>
</svg>
</button>
</li>
<li class="active">
<a href="/">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
fill="#e8eaed">
<path
d="M240-200h120v-200q0-17 11.5-28.5T400-440h160q17 0 28.5 11.5T600-400v200h120v-360L480-740 240-560v360Zm-80 0v-360q0-19 8.5-36t23.5-28l240-180q21-16 48-16t48 16l240 180q15 11 23.5 28t8.5 36v360q0 33-23.5 56.5T720-120H560q-17 0-28.5-11.5T520-160v-200h-80v200q0 17-11.5 28.5T400-120H240q-33 0-56.5-23.5T160-200Zm320-270Z"/>
</svg>
<span>Home</span>
</a>
</li>
<li>
<a href="/playerDetails">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
fill="#e8eaed">
<path
d="M480-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM160-240v-32q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v32q0 33-23.5 56.5T720-160H240q-33 0-56.5-23.5T160-240Zm80 0h480v-32q0-11-5.5-20T700-306q-54-27-109-40.5T480-360q-56 0-111 13.5T260-306q-9 5-14.5 14t-5.5 20v32Zm240-320q33 0 56.5-23.5T560-640q0-33-23.5-56.5T480-720q-33 0-56.5 23.5T400-640q0 33 23.5 56.5T480-560Zm0-80Zm0 400Z"/>
</svg>
<span>Profile</span>
</a>
</li>
</ul>
</nav>
<main>
<div class="grid">
<article>
<img src="https://www.mig-welding.co.uk/forum/data/avatars/s/40/40757.jpg" alt="Sample photo">
<div class="text">
<h3>Seamlessly visualize quality</h3>
<p>Hello</p>
<button>Here's why</button>
</div>
</article>
<article>
<img src="https://www.mig-welding.co.uk/forum/data/avatars/s/40/40757.jpg" alt="Sample photo">
<div class="text">
<h3> Seamlessly visualize quality</h3>
<p>Hello</p>
<button>Here's why</button>
</div>
</article>
</div>
</main>
:root{
--base-clr: #11121a;
--header-clr: #8a918c;
--header-text-clr: #2d302e;
--line-clr: #42434a;
--hover-clr: #222533;
--text-clr: #e6e6ef;
--accent-clr: #5e63ff;
--secondary-text-clr: #b0b3c1;
--header-bar-height: 40px;
}
*{
margin: 0;
padding: 0;
}
html{
font-family: Poppins, 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.5rem;
}
body{
min-height: 100vh;
min-height: 100dvh;
background-color: var(--base-clr);
color: var(--text-clr);
}
.grid{
display: grid;
padding:auto;
grid-template-areas:
"header navbar content";
}
main{
grid-template-columns: auto 1fr;
display:flex;
grid-area: content;
padding: min(30px, 7%);
box-sizing:border-box;
}
main p{
color: var(--secondary-text-clr);
margin-top: 5px;
margin-bottom: 15px;
}
article{
border: 1px solid var(--line-clr);
box-shadow: 2px 2px 6px 0px rgba(0, 0, 0, 0.3);
border-radius: 1em;
margin-bottom: 20px;
padding: min(3em, 15%);
h2, p { margin-top: 1em }
}
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>GridCss</title>
<link href="./app.css" rel="stylesheet"/>
</head>
<body>
<header>
Header
</header>
<main>
<div class="grid">
<article>
<img src="https://www.mig-welding.co.uk/forum/data/avatars/s/40/40757.jpg" alt="Sample photo">
<div class="text">
<h3>Seamlessly visualize quality</h3>
<p>small text</p>
<button>Here's why</button>
</div>
</article>
<article>
<img src="https://www.mig-welding.co.uk/forum/data/avatars/s/40/40757.jpg" alt="Sample photo">
<div class="text">
<h3> Seamlessly visualize quality</h3>
<p>tiny</p>
<button>Here's why</button>
</div>
</article>
</div>
</main>
</body>
</html>
Remove unnecessary wrappers like 'spa' and 'app'. Use display:grid on the 'grid' class to make div stand side by side. Use display:flex on the 'main' wrapper to expand box when more content is added.