So I wrapped my content in the layout component and all my other pages push the footer to the bottom because the content is bigger than the actual screen. However, I have one page that has less content and now my footer is awkwardly in the middle if I view it on a bigger height screen.
So here is my footer css
export const FooterContainer = styled.div`
background-color: #101522;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: absolute;
bottom: 0;
width: 100%;
`
My layout div css
.layout {
padding-bottom: 160px;
position: relative;
}
My layout component
return (
<>
<Sidebar isOpen={isOpen} toggle={toggle} />
<Navbar toggle={toggle} />
<div className="layout">
<main>{children}</main>
<Footer />
</div>
</>
)
}
Then in my page where my footer isn't sticking to the bottom this is my code
<Layout>
<div className="resource__container">
<h1 className="post__heading">
Here are some resources to learn web development
</h1>
<Posts posts={posts} key={posts.id} />
</div>
</Layout>
So here is a pic showing what is happening
The top black bar is the Navbar
The red section is my .resource__container
The white space below that is the padding-bottom: 160px from the .layout <div>
Then the last black space is the footer
After that it's just <main> but technically nothing there, so I don't why it isn't sticking to the bottom
Given a HTML structure like:
<body>
<header>…</header>
<main>…</main>
<footer>…</footer>
</body>
The solution to stick the footer at the bottom is using flexbox:
body {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main {
flex: 1;
}
The key is the min-height: 100vh as well as flex: 1 of the main tag.
Useful resources:
https://dev.to/mokkapps/sticky-footer-in-gatsbyjs-using-flexbox-5162
https://css-tricks.com/couple-takes-sticky-footer/
https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/
Related
So what I've got is a landing page that should show a.) a header b.) a large picture that fills the screen on desktop and c.) a navbar. The navbar should scroll along the page once it's reached the top of the page.
Now, the only way I would know to ensure that all three of those elements fit perfectly into the viewport on desktop is with max-height: 100vh in a parent element. However, I'd like to make the navbar scroll along once it's at the top of the screen. This isn't possible when the navbar is in its own container, because it'll stop scrolling along once it's hit the bottom of its container.
Does anyone know of a fix? Below is a sample of the structure I'm trying to use right now:
<div class="container-top">
<header>
<!--- ...header content... -->
</header>
<div>
<img src="1080p_image.png">
</div>
<nav class="sticky-top">
<!-- ...navbar content... -->
</nav>
</div>
<div class="other-content">
<!-- ...other content... -->
</div>
.container-top{
max-height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-between;
}
img{
width: 100vw;
}
header{
background-color: darkgray;
height: 5rem;
z-index: 1;
}
nav{
background-color: darkgray;
height: 5rem;
z-index: 1;
}
.sticky-top{
position: sticky;
top: 0;
}
.other-content{
height: 100rem;
}
Have you tried moving your nav into its own div below div.container-top?
<div class="container-top">
<header>
<!-- ...header content -->
</header>
<div>
<img/>
</div>
</div>
<div>
<nav class="sticky-top">
<!-- ..navbar content... -->
</nav>
</div>
<div class="other-content">
<!-- ...other content... -->
</div>
And if you want these elements to take up 100vh:
.container-top {
max-height: 75vh;
display: flex;
flex-direction: column;
justify-content: space-between;
}
nav {
max-height: 25vh;
}
Lemme know how that works for ya.
I am working on a simplistic website to show pictures in a single stream. To keep javascript to a minimum (just lazy loading), I only use a single relatively high-resolution version of each image and then rely on CSS to resize.
My question is how the rest of the website, at least the logo and the menu, can be best resized relative to the size of the images. After reading the CSS grid guide I decided to use a grid with grid-auto-flow: row.
The problem: I want the logo to flush left with the left of the top image and the menu to flush right with the right of the top image (all horizontal images have the same width).
My current code either aligns logo and menu to the corners of the page (as with the code below) or centers both (if I move the header into the grid as first item)
#main{
height: max-content;
display: grid;
grid-auto-flow: row;
grid-row-gap: 8em;
place-items: center center;
}
.photo_horizontal, .photo_vertical{
object-fit: contain;
height: auto;
}
.photo_horizontal{
width: 80vw;
max-height: 80vh;
}
.photo_vertical{
width: 60vw;
max-height: 90vh;
}
/* THE HEADER */
header{
display: grid;
grid-auto-flow: column;
}
#logo{
width: 15em;
justify-self: start;
}
header > div{
margin: auto 0 0 auto;
}
<header>
<img id="logo" src="https://via.placeholder.com/500x100/ff7f7f/333333?text=some%20website"/>
<div>
menu1
menu2
</div>
</header>
<div id="main">
<img class="photo_horizontal" src="https://picsum.photos/3000/2000"/>
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_horizontal" src="https://picsum.photos/3000/2000" />
</div>
Is there an elegant way to resize images relative to the viewport but still align other content accordingly? I tried to pad logo and menu left/right but the necessary padding depends on the actual size of the image.
A pen can be found here.
To clarify, this is how it currently is and this is what I want.
The main problem is setting .photo_horizontal's .max-height: 80vh; causes it to not always honor the width: 80vw; which means the width of the .photo_horizontal is not easily calculated. That makes it difficult to make the <header> the same width.
You can do this:
header {
width: 80vw;
margin: auto;
}
But it only works if you also get rid of the max-height: 80vh rule for .photo_horizontal.
https://codepen.io/km0ser/pen/LYpqeYB
Why not include the header within #main
/* Nothing wrong with CSS grid, just Flexbox is simpler */
#main {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid;
}
/* height being auto will keep the aspect ratio */
/* horizontal photo take full width */
.photo_horizontal {
max-width: 100%;
}
/* horizontal photo take some portion of width */
.photo_vertical {
max-width: 80%;
}
header {
display: flex;
width: 100%;
}
#logo {
width: 15em;
}
header>div {
margin: auto 0 0 auto;
}
<div id="main">
<header>
<img id="logo" src="https://via.placeholder.com/500x100/ff7f7f/333333?text=some%20website" />
<div>
menu1
menu2
</div>
</header>
<img class="photo_horizontal" src="https://picsum.photos/3000/2000" />
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_horizontal" src="https://picsum.photos/3000/2000" />
</div>
Thanks to the answers here I figured out a solution. There are three components:
As #Zohir Salak pointed out, much simpler CSS can be obtained using flexbox.
The header can be part of main even though this is not essential to the solution.
As #kmoser pointed out, the max-height constraint on images makes it hard to set a proper max-width constraint for the header, a problem that isn't solved by 1. and 2. yet. However, since all of my pictures are 3:2 ratio, a max-height constrained can be turned into a max-width constrained easily and then combined with a min via max-width: min(80vw, 3 / 2 * 80vh);.
/* Nothing wrong with CSS grid, just Flexbox is simpler */
#main {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid;
}
/* height being auto will keep the aspect ratio */
/* horizontal photo take full width */
.photo_horizontal {
max-width: min(80vw, 3 / 2 * 80vh);
}
/* horizontal photo take some portion of width */
.photo_vertical {
max-width: min(80vw, 2 / 3 * 80vh);
}
header {
display: flex;
width: 100vw;
max-width: min(80vw, 3 / 2 * 80vh);
}
#logo {
width: 15em;
}
header>div {
margin: auto 0 0 auto;
}
<div id="main">
<header>
<img id="logo" src="https://via.placeholder.com/500x100/ff7f7f/333333?text=some%20website"/>
<div>
menu1
menu2
</div>
</header>
<img class="photo_horizontal" src="https://picsum.photos/3000/2000"/>
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_horizontal" src="https://picsum.photos/3000/2000" />
</div>
Alternatively, see the same code in a pen here.
I am using Materializecss to create React app. I have already applied flex inside my app class. And now I want to apply flex inside main tag where buttons get fixed at bottom of main tag & above the footer.
I have tried {margin-top: auto;} , justify-content: flex-end which didn't help. The buttons always print after content class. I can set the height of the content class, but small devices render view badly and it's not fixing my problem.
JSX code:
<div className="app">
<header> <header>
<main>
<div className="box">
<div className="content"> Long text less than 100 words <div>
<div className="buttons"> <button> Button-1 </button> <button> Button-2 </button>
<div>
<main>
<footer><footer>
<div>
My css
app {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main {
flex: 1 0 auto;
}
I want to stick my button above the footer. My content class has 100 words then the button should stick above the footer not rendered after the content class.
I would appreciate the help.
You haven't applied display:flex etc to the main element. If you do that the margin-top:auto will work.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
::before,
::after {
box-sizing: inherit;
}
.app {
display: flex;
min-height: 100vh;
flex-direction: column;
background: ;
}
main {
flex: 1;
display: flex;
flex-direction: column;
}
.buttons {
margin-top: auto;
}
<div class="app">
<header>header </header>
<main>
<div class="box">box</div>
<div class="content"> Long text less than 100 words </div>
<div class="buttons">
<button> Button-1 </button>
<button> Button-2 </button>
</div>
</main>
<footer>footer</footer>
</div>
I'm using a grid system with 3 columns in my SPA. The left and right list contain components that occupy 100 of the viewport height. The middle column contains a long list and would like to add a scrollbar just to the middle component. I've tried to wraw the middle component with several different scrollbar components but nothing works. I end up always with a main page scroll which leaves me only with the list component when scroll further down and left and right component are remaining remain to the top of the page.
Try adding overflow-y: scroll; on the middle component
const items = [...Array(100)].map((val, i) => `Item ${i}`);
const App = () => (
<div className="container">
<div className="left-col">
Left col
</div>
<div className="center-col">
<span>List</span>
<ul>
{items.map((item, i) => (<li key={`item_${i}`}>{ item }</li>))}
</ul>
</div>
<div className="right-col">
Right col
</div>
</div>
);
ReactDOM.render(<App />, document.getElementById('react'));
.container {
display: flex;
flex-direction: row;
height: 100vh;
}
.left-col {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
background: #ddd;
}
.center-col {
flex: 1;
background: #aaa;
overflow-y: scroll;
}
.right-col {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
background: #e7e7e7;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="react"></div>
Found the solution, need to set fixed height to left and right component and overflow:scroll to middle component.
I have a box (shopping cart) which I want it to be fixed at the bottom of the page.
But if the page is not long enough, or the user scroll to the end of the page, so that the footer is in the viewport. In this case I want the shopping cart box to be right above the footer.
Is it possible to do this without JS?
Thanks
answer only for the fun, you should relay on javascript to make it solid.
There could be a risky trick with position:sticky, floatting pseudo and display resetting.
aside,
footer {
position: sticky;
bottom: 0;
background: white;
border: solid;
clear: both;
z-index: 1;
}
footer {
z-index: 0;/*hide it from aside */
}
html:before {/* push sticky elements down */
content: "";
float: left;
height: 100vh;
}
body {
margin:0;
display: inline;/* get body scrolling and block formatting context off the game */
}
<main>main<br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/> end main</main>
<aside>aside at bottom !</aside>
<footer>footer</footer>
You can play a little with and test it with content, but remenber, its not reliable, sticky not implemented everywhere and behavior can varie from a browser to another, from an update to another in the most funny and unexpected ways.
Your question is not very clear, so I'll try to answer it as best as I understand.
Getting your footer to sit on the bottom of a short page
To achieve this effect, flexbox comes in very handy. First, set the
body's style to : display:flex;
flex-direction: column;
min-height: 100vh;
Setting display:flex makes all child elements on the page (i.e. in the body tag) flex items, hence offering us the opportunity to style said elements as such. Setting flex-direction to column also ensures that all child elements of body are stacked vertically.
Now, the min-height: 100vh; makes the body span at least 100% of the viewport height.
To get an element (in this case your shopping cart box. Let's call it .shopping-cart-box from here on out) to "push" the footer to the bottom of the viewport, you can then set it's flex (or flex-grow, to be precise) value to 1. This makes it take up the rest of the available space.
Remember the body is at 100% of viewport height. If your navigation menu takes up, say, 10% and footer takes up 5% of the viewport height respectively, the .shopping-cart-box with flex: 1; will then fill up the rest of the 85% of viewport height, essentially "pushing" the footer to the bottom of the page.
Making your shopping cart box sit on top of the footer
Now that we have the footer at the bottom and .shopping-cart-box taking up the rest of the available space, we need to force its contents to align bottom.
We can do this by adding display: flex;
flex-direction: column; to .shopping-cart-box. That, again, allows us to treat all child elements of .shopping-cart-box as flex items.
Assuming we have a child element .shopping-cart-product inside .shopping-cart-box, we can set align it to the bottom of its parent container in two ways:
using margin-top: auto or
align-self: flex-end
A visual representation can be found below with the provided code snippet:
/* RELEVANT CODE*/
.body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.shopping-cart-box {
display: flex;
flex: 1;
}
.shopping-cart-product {
margin-top: auto; /* or align-self: flex-end; */
}
/*CODE FOR AESTHETICS */
.container {
width: 90%;
margin-left: auto;
margin-right: auto;
}
.nav {
display: flex;
flex-direction: row;
padding: 12px;
}
.logo {
display: block;
margin-right: auto;
}
/* Footer */
.footer {
background-color: #013940;
padding: 18px 12px;
color: white;
margin-top: 6px;
}
.ui.item.menu,
.ui.item.menu .item {
width: 40% !important;
margin: 0;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.min.css" rel="stylesheet" />
<body class="body">
<header>
<nav class="nav">
<a href="#" class="logo">
<h1>
ShopperStack</h1>
</a>
<ul class="ui two item menu nav--links">
<li class="item">
Home
</li>
<li class="item">
About
</li>
</ul>
</nav>
</header>
<div class="container">
<p>
This is a block of text on the upper part of the page
</p>
</div>
<div class="shopping-cart-box">
<div class="shopping-cart-product container">
<form action="" class="ui segment form">
<div class="field">
<h3 class="header">Place Order</h3>
<p class="label">ACME SuperBlaster 4000</p>
<input type="submit" value="Buy Now" class="ui button">
</div>
</form>
</div>
</div>
<footer class="footer">
<section class="container">
<h3>Thanks for visiting ShopperStack!</h3>
</section>
</footer>
</body>