How to fix sidebars using css-grids - html

I would like to fix both the header and the sidebars positioned with css-grids. I tried to use position:fixed but it ends up messing up the interface. Is there a simple way to do this? Or is the only way relative positioning and height/width adjustments? I wouldn't want to make the use of css-grids pointless...
Here's the link to the Codepen if you find it easier (code without lipsum included below): https://codepen.io/fergos2/pen/MWgLqgL?editors=1100
Thanks in advance for helping this newbie!
<div class="container">
<header class="header pd">Header</header>
<div class="left-sidebar pd">
<div class="box-1 pd">
Box-1
</div>
<footer class="footer pd">
Footer
</footer>
</div>
<div class="main-content pd">
Main content
</div>
<div class="right-sidebar pd">
<div class="box-2 pd">
Box-2
</div>
<div class="box-3 pd">
Box-3
</div>
</div>
</div>
.container {
width: 1000px;
margin: 30px auto;
background-color: #eee;
display: grid;
grid-template-rows: min-content 1fr;
grid-template-columns: 1fr 2fr 1fr;
grid-gap: 15px;
grid-template-areas: "head head head"
"leftbar main rightbar";
& > * {
background-color: pink;
color: #ggg;
font-size: 20px;
font-family: sans-serif;
}
}
.pd {
padding: 15px;
}
.header {
grid-area: head;
}
.left-sidebar {
grid-area: leftbar;
display: flex;
flex-direction: column;
justify-content: flex-start;
.box-1 {
color: red;
border: 1px solid purple;
margin-bottom: 5px;
}
.footer {
color: green;
border: 1px solid purple;
}
}
.main-content {
grid-area: main;
}
.right-sidebar {
grid-area: rightbar;
display: flex;
flex-direction: column;
justify-content: flex-start;
.box-2 {
color: red;
border: 1px solid purple;
margin-bottom: 5px;
}
.box-3 {
color: green;
border: 1px solid purple;
}
}
UPDATE:
position: -webkit-sticky;
position: sticky;
top: 0;
seems to work for the header but not for the sidebars (even when setting top:200px for example). Any suggestions on what to do with the sidebars?

Related

Positioning grid items in navigation bar

im trying to get my "Home" and "Clock" link up inside the navigation-bar. I am clueless why the CSS i wrote doesnt solve this issue. Can someone help me out? Ive tried using the grid property for the children of the navigation-bar, but they seem to not fit. Is there a better way to do this?
<link rel="stylesheet" type="text/css" href="styles.css" />
<div class="container">
<div class="header">Home</div>
<div class="navigation">
Navigation
<ul>
<li>Home</li>
<li>Clock</li>
</ul>
</div>
<div class="content-large">
Overview
<div class="grid-item">
<form>
<button class="cal_btn" formaction="">Calendar</button>
</form>
</div>
<div class="grid-item">
<form>
<button class="cal_btn" formaction="">Show</button>
</form>
</div>
<div class="grid-item">
<form>
<button class="cal_btn" formaction="/tagung/">Add</button>
</form>
</div>
<div class="grid-item">
<form>
<button class="cal_btn" formaction="/cal/">Edit</button>
</form>
</div>
<div class="grid-item">
<form>
<button class="cal_btn" formaction="">Delete</button>
</form>
</div>
</div>
<div class="content-small">. . .</div>
<div class="content-small">. . .</div>
<div class="footer">Footer</div>
</div>
And the CSS file below
body {
margin: 0;
}
.container {
width: 100vw;
height: 100vh;
display: grid;
font-family: "Quicksand", sans-serif;
font-weight: bold;
font-size: 1.5rem;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 50px 50px 1fr 1fr 100px;
grid-gap: 0.5rem;
padding: 0.5rem;
box-sizing: border-box;
}
.header,
.navigation,
.footer,
.content-large,
.content-small {
padding: 0.5rem;
border: 1px solid black;
}
.container > .header {
grid-column: 1/4;
}
.container > .navigation {
grid-column: 1/4;
background-color: #eee;
}
.navigation ul {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-column: 1/4;
font-size: large;
}
.nav-element {
font-size: 10px;
background-color: blue;
}
.container > .content-large {
grid-row: 3 / span 2;
grid-column: 1/3;
}
.grid-item {
padding: 1px;
}
.nav-item {
grid-column: 1/3;
}
.container > .cal_btn {
transition-duration: 0.4s;
background-color: #e7e7e7;
color: black;
border: 2px solid black;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
width: 300px;
height: 100px;
}
.cal_btn:hover {
background-color: aliceblue;
color: cornflowerblue;
}
.container > .footer {
grid-column: 1/4;
}
Thanks in advance!
P.S. Ive added a link to my Codesandbox here.
The main reason why you are not getting the desired layout is that display: grid; rule for .navigation ul makes the ul a block element, which gets the whole width of its parent. There may be various ways to achieve this. A solution with minimal changes to your code is replacing display: grid; with
display: inline-grid;
width: 200px;
Of course you can adjust the width as you wish.

CSS: Need help how to get my two items in my container to be placed correctly

I have a problem with how i am supposed to center my text in the middle of the box and get my number (01, 02 etc) in the top left corner?
I am using flexbox to first center all my contents and then align-self my heading to flex start. All fine and dandy but as you can see my heading is not in the top right corner. How would i make sure the heading is in the top left corner and my text is in the center of the box and not slightly off center?
I have tried to set margin right on auto to push the heading to the left, it works but my text is then pushed all the way to the right.
How would I go ahead of fixing this?
footer {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.box {
min-height: 354.48px;
max-height: 354.48px;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
}
.box h2 {
font-size: 2rem;
}
.how-it-works {
background-color: #c7ddea;
}
.O1 {
background-color: white;
}
.O1 h2 {
align-self: flex-start;
}
.O2 {
background-color: #e7e7e7;
}
.O2 h2 {
align-self: flex-start;
}
.O3 {
background-color: #fff;
}
.O3 h2 {
align-self: flex-start;
}
.O4 {
background-color: #f17949;
}
.O4 h2 {
align-self: flex-start;
}
.O5 {
background-color: #fff;
}
.O5 h2 {
align-self: flex-start;
}
<footer>
<div class="box how-it-works">
<h1>How it works?</h1>
</div>
<div class="box O1">
<h2>01</h2>
<p>Answer a few questions about yourself</p>
</div>
<div class="box O2">
<h2>02</h2>
<p>Choose a plan. Get a quote.</p>
</div>
<div class="box O3">
<h2>03</h2>
<p>Answe some questions about your medical history</p>
</div>
<div class="box O4">
<h2>04</h2>
<p>Wait 90 sec to get approved.</p>
</div>
<div class="box O5">
<h2>05</h2>
<p>Done!</p>
</div>
</footer>
You could do something like this:
footer {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.box {
position: relative;
min-height: 354.48px;
max-height: 354.48px;
display: flex;
flex-direction: column;
justify-content: center;
padding: 1rem;
}
.box h2 {
font-size: 2rem;
line-height: 0;
position: absolute;
top: 1rem;
left: 1rem;
}
.box p {
text-align: center;
}
.how-it-works {
background-color: #c7ddea;
}
.O1 {
background-color: white;
}
.O2 {
background-color: #e7e7e7;
}
.O3 {
background-color: #fff;
}
.O4 {
background-color: #f17949;
}
.O5 {
background-color: #fff;
}
<footer>
<div class="box how-it-works"><h1>How it works?</h1></div>
<div class="box O1">
<h2>01</h2>
<p>Answer a few questions about yourself</p>
</div>
<div class="box O2">
<h2>02</h2>
<p>Choose a plan. Get a quote.</p>
</div>
<div class="box O3">
<h2>03</h2>
<p>Answe some questions about your medical history</p>
</div>
<div class="box O4">
<h2>04</h2>
<p>Wait 90 sec to get approved.</p>
</div>
<div class="box O5">
<h2>05</h2>
<p>Done!</p>
</div>
</footer>
If I understood well what you need, one solution could be adding this to .box class:
.box{
flex-direction: column;
}

Getting an Image to auto-resize inside a CSS Grid

Very beginner to HTML/CSS and I need some help with fitting in image inside a CSS Grid.
I have created a simple CSS grid and when I'm trying to fit an image inside one of the grid, I was able to get width to fit properly, but the height is something that will not change.
I've tried obejct-fit, max-height with ratios...etc.
Would you please help and guide me on how to get this done?
This is my codepen currently working on: https://codepen.io/jyjang703/pen/poodOgw
#main {
min-height: 100vh;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 250px 300px 300px auto;
grid-gap: 10px;
background-color: white;
grid-template-areas: "header header header header" "section1 section2 section3 section4" "footer footer footer footer";
}
#title {
grid-area: header;
border: 1px solid red;
background-color: red;
text-align: center;
}
#section1 {
grid-area: section1;
border: 1px solid red;
width: 100%;
}
#section1 img {
object-fit: cover;
position: relative;
overflow: hidden;
max-width: 100%;
max-height: 100%;
}
#section2 {
grid-area: section2;
border: 1px solid red;
}
#section3 {
grid-area: section3;
border: 1px solid red;
}
#section4 {
grid-area: section4;
border: 1px solid red;
}
#footer {
grid-area: footer;
border: 1px solid red;
}
<main id="main">
<header id="title">
<h1> Allen Iverson</h1>
</header>
<section id="section1">
<div id="img-div">
<figure>
<img src="https://fsa.zobj.net/crop.php?r=FwHUQXbzIfSpz4awUIaTcY3NIgHVe1mSFMPlsB6rpnNmbj9mHPRpVHtH7c8RgxuGUffOqlWYgSbRNw4hXsKEL4NpVjgwRglygtByR-SVELuRZrvPVOfhBVpCkcS0FNh74XcecRFJpdkNtQwOy_rZO2Ftc5H606i6-pDgEjbe2Aqrn3yUNiwkTPLkq34" alt="">
<figcaption>
It's not about size, it's about size of your heart
</figcaption>
</figure>
</div>
</section>
<section id="section2">
</section>
<section id="section3">
</section>
<section id="section4">
</section>
<footer id="footer">
I am a Footer
</footer>
</main>
You should remove the #img-div. Convert the figure to a flexbox, and constrain it's height:
#section1 figure {
display: flex;
flex-direction: column;
height: 100%;
margin: 0;
padding: 0.5em;
box-sizing: border-box;
}
Set the imgs flex to 1, and use min-height: 0 to let it shrink:
#section1 img {
display: block;
object-fit: scale-down;
max-width: 100%;
flex: 1;
min-height: 0;
}
Example (click run and then full page):
#main {
min-height: 100vh;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 250px 300px 300px auto;
grid-gap: 10px;
background-color: white;
grid-template-areas: "header header header header" "section1 section2 section3 section4" "footer footer footer footer";
}
#title {
grid-area: header;
border: 1px solid red;
background-color: red;
text-align: center;
}
#section1 {
grid-area: section1;
border: 1px solid red;
}
#section1 figure {
display: flex;
flex-direction: column;
height: 100%;
margin: 0;
padding: 0.5em;
box-sizing: border-box;
text-align: center;
}
#section1 img {
object-fit: scale-down;
max-width: 100%;
flex: 1;
min-height: 0;
}
#section2 {
grid-area: section2;
border: 1px solid red;
}
#section3 {
grid-area: section3;
border: 1px solid red;
}
#section4 {
grid-area: section4;
border: 1px solid red;
}
#footer {
grid-area: footer;
border: 1px solid red;
}
<main id="main">
<header id="title">
<h1> Allen Iverson</h1>
</header>
<section id="section1">
<figure>
<img src="https://fsa.zobj.net/crop.php?r=FwHUQXbzIfSpz4awUIaTcY3NIgHVe1mSFMPlsB6rpnNmbj9mHPRpVHtH7c8RgxuGUffOqlWYgSbRNw4hXsKEL4NpVjgwRglygtByR-SVELuRZrvPVOfhBVpCkcS0FNh74XcecRFJpdkNtQwOy_rZO2Ftc5H606i6-pDgEjbe2Aqrn3yUNiwkTPLkq34" alt="">
<figcaption>
It's not about size, it's about size of your heart
</figcaption>
</figure>
</section>
<section id="section2">
</section>
<section id="section3">
</section>
<section id="section4">
</section>
<footer id="footer">
I am a Footer
</footer>
</main>

How can I resolve Grid layout problem in this case?

I've got some problems when I'am trying to make my section with Grid layout. Where exactly I make mistake? Can someone explaine me, please?
HTML
<body>
<header>
<div class="grid-wrapper">
<div class="item1"><span>Item 1</span></div>
<div class="item2"><span>Item 2</span></div>
<div class="item3"><span>Item 3</span></div>
<div class="item4"><span>Item 4</span></div>
<div class="item5"><span>Item 5</span></div>
</div>
</header>
</body>
CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #969d9f;
}
header {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
background-color: #969d9f;
}
.grid-wrapper {
border: 1px solid red;
width: 1200px;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(2, 1fr);
}
.item1, .item2, .item3, .item4, .item5 {
border: 1px solid grey;
background-color: #636564;
height: 360px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 40px;
}
.item1 { width: 750px; }
.item2 { width: 360px; }
.item3 { width: 555px; }
.item4 { width: 555px; }
.item5 { width: 1200px; }
So the main question is how can I correctly display my blocks and where is my main mistake that I make?
Here is some pics:
Thank you for your attention!
its my opinion
HTML
<body>
<header>
<div class="grid-wrapper">
<div class="item1"><span>Item 1</span></div>
<div class="item2"><span>Item 2</span></div>
<div class="item3"><span>Item 3</span></div>
<div class="item4"><span>Item 4</span></div>
<div class="item5"><span>Item 5</span></div>
</div>
</header>
</body>
CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #969d9f;
}
header {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
background-color: #969d9f;
}
.grid-wrapper {
border: 1px solid red;
width: 1200px;
display: grid;
grid-gap: 20px;
grid-template-areas: "item1 item1 item2" /* make grid area */
"item3 item4 item4"
"item5 item5 item5";
grid-template-columns:(1fr, 1fr, 1fr); /* set width of colums */
}
.item1, .item2, .item3, .item4, .item5 {
border: 1px solid grey;
background-color: #636564;
height: 360px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 40px;
}
.item1 {grid-area: item1} /* connect items with grid area */
.item2 {grid-area: item2}
.item3 {grid-area: item3}
.item4 {grid-area: item4}
.item5 {grid-area: item5}
Your layout isn't a "normal" grid (your rows 1 & 2 have cells with different widths from each other), so to resolve it, a solution could be to create more columns (3/4/5 columns: it depends by cells width and if the biggests [1&4] are equals or not) and play, for example, with grid-template-areas to create items that can... "fill more than 1 cell": in background there is a grid, but with this "trick" you can transform it as your layout.
This is a useful guide for more informations about CSS grid: https://css-tricks.com/snippets/css/complete-guide-grid/
Another solution is to use flexbox also for those rows :-)
Try it:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #969d9f;
}
header {
width: 100%;
/*height: 100vh;*/
display: flex;
justify-content: center;
background-color: #969d9f;
}
.grid-wrapper {
border: 1px solid red;
width: 100%;
max-width:1200px;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
"item1 item1 item1 item2"
"item3 item4 item4 item4"
"item5 item5 item5 item5";
}
.item1, .item2, .item3, .item4, .item5 {
border: 1px solid grey;
background-color: #636564;
height: 360px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 40px;
}
/*.item1 { width: 750px; }
.item2 { width: 360px; }
.item3 { width: 555px; }
.item4 { width: 555px; }
.item5 { width: 1200px; }*/
.item1 {
grid-area: item1;
}
.item2 {
grid-area: item2;
}
.item3 {
grid-area: item3;
}
.item4 {
grid-area: item4;
}
.item5 {
grid-area: item5;
}
<header>
<div class="grid-wrapper">
<div class="item1"><span>Item 1</span></div>
<div class="item2"><span>Item 2</span></div>
<div class="item3"><span>Item 3</span></div>
<div class="item4"><span>Item 4</span></div>
<div class="item5"><span>Item 5</span></div>
</div>
</header>
P.S. Maybe it is better don't use a fixed widths in a world of mobile device, so I changed your witdh:1200px with a max-width:1200px, but well you can change it
if you do not care about it ;-)

Make grid item consume the space of another item that has been removed

Essentially what I need to happen is to set up a grid, but if one of the elements is missing, another element stretches to fill the space.
This is an example Pen of where I'm currently at:
https://codepen.io/Rockster160/pen/JMLaXY
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas: "sidebar header"
"sidebar content"
"sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.footer {
grid-area: footer;
background: orange;
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
footer is an optional element, so when it doesn't exist (commented out as in the code) then content should stretch and line up with the bottom of sidebar.
I've tried a variety of different combinations using min/max content and different auto placements, but no luck. I thought if I had multiple elements named content it might work as well, but no luck there either.
Any help is greatly appreciated!
You are forcing the 3rd row to be 50px in the grid style.
Change it to be adapted to the content, and set the 50px as height in the footer itself:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto max-content; /* changed last 50px to max-content*/
grid-template-areas: "sidebar header"
"sidebar content"
"sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.footer {
grid-area: footer;
background: orange;
height: 50px; /* added */
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
And another posibility, thanks to Michael_B. The sintax of grid-template-rows is clearer:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px 1fr auto;
grid-template-areas: "sidebar header"
"sidebar content"
"sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.footer {
grid-area: footer;
background: orange;
height: 50px; /* added */
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
The easiest way to do this is to use the :last-child selector:
.content:last-child {
grid-row: content / footer;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas: "sidebar header" "sidebar content" "sidebar footer";
margin-bottom: 2rem;
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
.content:last-child {
grid-row: content / footer;
}
.footer {
grid-area: footer;
background: orange;
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
Or, alternatively, we could reverse the order of the .content and .footer elements in the HTML (as below) and use the CSS negation operator (:not()) to determine that the .content element should take up extra space if it is not preceded by a .footer element:
:not(.footer) + .content {
grid-row: content/footer;
}
which styles a .content element that is not immediately preceded by a .footer sibling in such a way that it starts in the grid-row identified by content and ends in the grid-row identified by footer:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
div {
box-sizing: border-box;
}
.grid {
height: 100%;
width: 100%;
background: white;
border: 2px solid red;
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas: "sidebar header" "sidebar content" "sidebar footer";
}
.sidebar {
grid-area: sidebar;
background: green;
}
.header {
grid-area: header;
background: lightblue;
}
.content {
grid-area: content;
background: blue;
border: 5px solid black;
}
:not(.footer)+.content {
grid-row: content/footer;
}
.footer {
grid-area: footer;
background: orange;
}
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<!-- <div class="footer"></div> -->
</div>
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
References:
grid-row.
:last-child.
Negation pseudo-class:not().
Sometimes things are simpler with flexbox.
Since your container has a defined height (the viewport), you can use flex-flow: column wrap to create both columns.
Then use flex: 1 on the content item, which tells it to consume free space.
When the footer is present, the content makes space for it. When the footer is not present, the content consumes all space.
.grid {
display: flex;
flex-flow: column wrap;
height: 100vh;
background: white;
border: 2px solid red;
}
.sidebar {
flex: 0 0 100%;
width: 250px;
background: green;
}
.header {
flex: 0 0 100px;
width: calc(100% - 250px);
background: lightblue;
}
.content {
flex: 1;
width: calc(100% - 250px);
border: 5px solid black;
background: blue;
}
.footer {
flex: 0 0 50px;
width: calc(100% - 250px);
background: orange;
}
body { margin: 0; }
div { box-sizing: border-box; }
<!-- WITH FOOTER -->
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>
<hr>
<!-- WITHOUT FOOTER -->
<div class="grid">
<div class="sidebar"></div>
<div class="header"></div>
<div class="content"></div>
</div>
Change your .grid class to
.grid {
display: grid;
grid-template-columns: 250px auto;
grid-template-rows: 100px auto 50px;
grid-template-areas:
"sidebar header"
"sidebar content"
"sidebar content";
}
when you comment your footer tag as in your pen, grid is still waiting to have a footer element there, so it's kinda "saving space" for this element there