Creating a sticky footer inside a 3-row grid - css

I'm trying to create a 3-row layout (header, content, footer) using:
min-height: 100vh;
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: 100%; //keep this to prevent content overflowing outside container
grid-gap: 2em;
grid-template-areas:
"header"
"content"
"footert";
I'm using align-self: end to have the footer always be at the bottom of the page.
The problem is, I want to make the footer sticky, so as the user scrolls up or down along the content, the footer always remains visible at the bottom.
If I use position: absolute or fixed though, this seems to break the footer out of the grid. Content continues to scroll over it like it wasn't there, and sometimes it also reduces the width of footer items.
Any ideas how to do this?

You could use position: sticky along with ::before pseudo-element to always keep some gap between the content and the footer.
Push the pseudo-element above the footer by translating it in negative Y-direction and then give it a background color same as that of the body. That will make it look like there's a gap between the footer and the content.
body {
margin: 0;
background: #fff;
}
.container {
height: 100vh;
display: grid;
grid-template-rows: 30px 400px 30px;
grid-gap: 1em;
}
.header {
background: #22f;
}
.content {
background: #fc9;
}
.footer {
background: #ee1;
position: sticky;
bottom: 0;
}
.footer::before {
content: '';
position: absolute;
background: #fff;
width: 100%;
height: 1em;
transform: translateY(-100%);
}
<div class="container">
<div class="header">Header</div>
<div class="content">Content</div>
<div class="footer">Footer</div>
</div>

Is this? Just add position: sticky and bottom:0. Also grid area is not needed.
.container {
min-height: 100vh;
display: grid;
grid-template-rows: auto 1500px auto;
grid-template-columns: 100%;
grid-gap: 2em;
}
.header {
background: pink;
height: 50px;
}
.content {
background: aqua;
}
.footer {
background: sandybrown;
height: 50px;
position: sticky;
bottom: 0;
}
<div class="container">
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</div>

You can try like below:
.container {
min-height: 100vh;
display: grid;
grid-template-rows: auto 1fr auto;
grid-gap: 2em;
}
.header {
background: pink;
height: 50px;
}
.content {
background: aqua;
font-size:40px;
}
.footer {
box-shadow:0 -2em 0 0 #fff;
background: sandybrown;
height: 50px;
position: sticky;
bottom: 0;
}
body {
margin:0;
}
<div class="container">
<div class="header"></div>
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer eleifend enim sapien. Proin facilisis ornare mi, ut eleifend odio dictum vestibulum. Pellentesque arcu ex, vehicula eget porta at, maximus ac massa. In hac habitasse platea dictumst. Sed ultrices et massa a ultrices. Pellentesque scelerisque, neque vitae semper bibendum, risus dolor suscipit felis, id porttitor nisi justo et lectus. Mauris interdum ligula imperdiet nunc ornare, </div>
<div class="footer"></div>
</div>

Related

Float left bug in Firefox when when parent is absolutly positioned?

I have an unusual layout requirement but Ive got it working in Chrome, Edge and IE11, only Firefox doen't work making me think it could be a bug with the browser.
Here is how the page should look:
But this is how it looks is Firefox:
Update: I also got this working on Chrome without float: left and instead using width: fit-content, however this and width: -moz-fit-content still don't work on Firefox.
The floated div with the red boarder doenst appear to be floated at all. As a result the blue box is off screen.
* {
box-sizing: border-box;
}
body {
padding: 0;
margin: 0;
}
.wrapper {
overflow: hidden;
}
.cont {
display: flex;
background: grey;
margin-left: auto;
margin-right: auto;
max-width: 1000px;
}
.col {
flex-basis: 50%;
min-height: 600px;
position: relative;
}
.col-1 {
display: flex;
flex-direction: column;
justify-content: center;
}
.col1-inner {
position: absolute;
top: 40px;
left: 0;
bottom: 40px;
right: -2000px;
}
img {
max-width: 100%;
width: auto;
height: 100%;
}
.content {
border: 2px solid red;
float: left;
height: 100%;
position: relative;
}
.content:after {
content: "";
background: blue;
display: flex;
width: 100px;
height: 100px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
<div class="wrapper">
<div class="cont">
<div class="col col-1">
<h1>Content</h1>
<p>Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff Stuff </p>
</div>
<div class="col">
<div class="col1-inner">
<div class="content">
<img src="https://images.unsplash.com/photo-1580152040915-ad6ceeaeb8c1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3450&q=80" />
</div>
</div>
</div>
</div>
</div>
https://codepen.io/_j_i_m_fb_/pen/GRgaKQE
Lame answer to the actual question
This is an edge case due to the large fixed units used. Chrome is collapsing the div when float is used. Firefox is not. To determine which browser is technically correct we must look at the appropriate specification. How boring is that... instead, here is a...
... possible solution for what you desire
I have created an alternative example with CSS Grid.
HTML
Simple layout. The body is used instead of an extra div, with two divs for the left and right column:
<body>
<div class="content">
<h1>Content</h1>
<p>Contents</p>
</div>
<div class="image">
<img src="https://placehold.it/3450x2300" />
</div>
</body>
CSS
The body:
body {
display: grid;
grid-template-columns: auto auto;
}
Establish the grid.
Create two equal width columns
The content div:
.content {
display: grid;
align-content: center;
max-width: 600px;
min-width: 400px;
background: grey;
padding: 0 20px;
margin: 0 0 0 auto;
}
Establish the inner grid
Vertically center the contents
Use appropriate max and min widths
Instead of justify-items: end, the left auto margin provides the horizontal centering. This is so the background doesn't stretch all the way to the left.
The image div:
.image {
position: relative;
max-width: 700px;
min-width: 500px;
background: linear-gradient(to right, grey 0, grey 50%, transparent 50%);
}
Position the pseudo-element in relation to this div
Restrict the width of the image so it doesn't get too large
Restrict the width of the image so it doesn't get too small
Create the background colour with a gradient that covers only a percentage of the image div
The img is contained like so:
img {
max-width: 100%;
padding: 40px 0;
}
Restrict width of image to parent div
Pad out as desired
Example
* {
box-sizing: border-box;
}
body {
margin: 0;
display: grid;
grid-template-columns: auto auto;
}
.content {
display: grid;
align-content: center;
max-width: 600px;
min-width: 400px;
background: grey;
padding: 0 20px;
margin: 0 0 0 auto;
}
.image {
position: relative;
max-width: 700px;
min-width: 300px;
background: linear-gradient(to right, grey 0, grey 50%, transparent 50%);
}
.image::after {
content: "";
height: 100px;
width: 100px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: blue;
position: absolute;
}
img {
max-width: 100%;
padding: 40px 0;
}
<div class="content">
<h1>Content</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec id bibendum enim. Integer blandit arcu lobortis, ultricies quam vitae, elementum urna. Nunc a mauris ex. Aenean egestas neque urna, eu euismod massa ultrices sit amet. Praesent imperdiet
dictum ante, quis viverra nibh volutpat eu. Sed tempor, quam in molestie tincidunt, eros massa condimentum arcu, ut tempus mauris ligula et arcu. Donec nec faucibus neque, sit amet tincidunt nulla. Nullam et mattis ipsum. Sed euismod porttitor justo
eu aliquet. Sed hendrerit finibus dignissim. Morbi id ipsum imperdiet, fringilla urna posuere, fermentum justo. Mauris eleifend, orci et eleifend consectetur, augue lacus hendrerit diam, eget dictum lacus sem vitae augue.</p>
</div>
<div class="image">
<img src="https://placehold.it/3450x2300" />
</div>

How to make Text A in container contained in container width that can be raised by Text B?

My Situation is as follows:
I have a container with a heading, a paragraph and a button. Texts are coming from the back-end. They get rendered in a Box with certain width (lets say 260px). Now I want the container to get more wider when the heading gets longer, but I don't want that to happen on the paragraph. The paragraph must be 100% width but it can wrap. The header and button cannot.
I've created a JSFiddle for you as an example: http://jsfiddle.net/swxmvgjr/2/
HTML:
<div class="container">
<h2>heading</h2>
<p>Nullam vel sem. Phasellus consectetuer vestibulum elit. Aenean commodo ligula eget dolor.</p>
<button>Link</button>
</div>
<div class="container">
<h2>heading that is a bit longer</h2>
<p>Nullam vel sem. Phasellus consectetuer vestibulum elit. Aenean commodo ligula eget dolor.</p>
<button>Link</button>
</div>
SCSS:
.container {
width: 260px;
background-color: #ccc;
padding: 20px;
margin-bottom: 20px;
h2 {
white-space: nowrap;
font-size: 250%;
}
p {
}
button {
padding: 10px;
border: 1px solid #333;
width: 100%;
}
}
https://jsfiddle.net/4ojc5fte/
seems someone already found a solution for me :)
.box {
display: inline-block;
border: 1px solid red;
min-width:260px;
}
.child {
display: flex;
}
.child div {
flex-grow: 1;
width: 0;
}

Position div B on top of div A

Hi I'm struggling with this issue.
Desktop:
Div A
Div B
But in responsive the divs have to change their position like this:
Responsive:
Div B
Div A
I made a jsfiddle:
#a {
height: 50px;
width: 100%;
background-color: red;
}
#b {
height: 50px;
width: 100%;
background-color: green;
}
<div id="a">
div 1
</div>
<div id="b">
div2
</div>
Is this possible?
You can use grid-row from CSS grid layout
section {
display: grid;
grid-auto-rows: minmax(50px, auto)
}
#a {
background-color: red;
}
#b {
background-color: green;
}
#media (max-width:768px) {
#b {
grid-row: 1
}
}
<section>
<div id="a">
div 1
</div>
<div id="b">
div2
</div>
</section>
Alternatives:
use order with also CSS grid layout
section {
display: grid;
grid-auto-rows: minmax(50px, auto)
}
#a {
background-color: red;
}
#b {
background-color: green;
}
#media (max-width:768px) {
#b {
order: -1
}
}
<section>
<div id="a">
div 1
</div>
<div id="b">
div2
</div>
</section>
use column-reverse from flexbox layout (as suggested by #G-Cyr in comments below)
section {
display: flex;
flex-direction: column;
}
div {
height: 50px;
}
#a {
background-color: red;
}
#b {
background-color: green;
}
#media (max-width:768px) {
section {
flex-direction: column-reverse;
}
}
<section>
<div id="a">
div 1
</div>
<div id="b">
div2
</div>
</section>
use flex-wrap/wrap-reverse with flexbox layout
section {
display: flex;
flex-wrap: wrap
}
div {
height: 50px;
flex: 0 100%
}
#a {
background-color: red;
}
#b {
background-color: green;
}
#media (max-width:768px) {
section {
flex-wrap: wrap-reverse
}
}
<section>
<div id="a">
div 1
</div>
<div id="b">
div2
</div>
</section>
use order with flexbox layout
section {
display: flex;
flex-direction: column;
}
div {
height: 50px;
}
#a {
background-color: red;
}
#b {
background-color: green;
}
#media (max-width:768px) {
#b {
order: -1
}
}
<section>
<div id="a">
div 1
</div>
<div id="b">
div2
</div>
</section>
If you need to support older browsers, you can do it this way as well. But this only works if the elements have a fixed height, otherwise you will have to play some other games.
#a {
height: 50px;
width: 100%;
background-color: red;
}
#b {
height: 50px;
width: 100%;
background-color: green;
}
#media (max-width:768px) {
#a {
position: relative;
top: 50px;
}
#b {
position: relative;
top: -50px;
}
}
<div id="a">
div 1
</div>
<div id="b">
div2
</div>
Here is another answer with 2 selector and a single rule :transform:scale(-1);
/* target the container and its direct-child */
div,
div>* {
transform: scale(-1);
}
#media (min-width:768px) {
div,
div>* {
transform: scale(1);
}
#a del {
text-decoration: none;
}
#a ins {
display: none;
}
<div>
<h1 id="a">HTML Ipsum Present<del>s</del><ins>ed</ins></h1>
<p id="b"><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci,
sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
</div>

CSS display: table-cell width 100% overflow-x expand

I have this two column layout, made with display: table and display: table-cell, and I want to put in the second column a div with horizontal scroll, but the table expands itself and the scroll goes to the entire page rather then the div.
HTML
<div class="wrapper">
<div id="one"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque convallis finibus metus. Suspendisse commodo rutrum sapien, eu faucibus metus. Nunc elementum augue eu aliquet condimentum.
</div>
<div id="two">
<div id="horizontal">
<img src="https://dl.dropbox.com/u/1218282/slideshow/1.jpg" />
<img src="https://dl.dropbox.com/u/1218282/slideshow/2.jpg" />
<img src="https://dl.dropbox.com/u/1218282/slideshow/3.jpg" />
<img src="https://dl.dropbox.com/u/1218282/slideshow/4.jpg" />
</div>
</div>
</div>
CSS
.wrapper {
display: table;
table-layout: fixed;
}
#one {
display: table-cell;
background-color: gray;
width: 200px;
}
#two {
display: table-cell;
width: 100%;
}
#horizontal {
width: 100%;
overflow-x: scroll;
white-space: nowrap;
}
#horizontal img {
max-width: 200px;
}
Here is the jsfiddle:
http://jsfiddle.net/cUCvY/2597/
In this example I'd like to have the horizontal scroll active on the div with the images inside and not on the page.
Hope i understood correctly:
.wrapper {
display: table;
table-layout: fixed;
width:100%
}
#one {
display: table-cell;
background-color: gray;
width: 200px;
}
#two {
}
#horizontal {
overflow-x: scroll;
white-space: nowrap;
}
#horizontal img {
max-width: 200px;
}
}
#media screen and (max-width: 400px) {
#one {
float: none;
margin-right:0;
width:auto;
border:0;
border-bottom:2px solid #000;
}
}
http://jsfiddle.net/cUCvY/2600/

Div Next To Circle

<article style="max-width:500px;" class="post" id="post-<?php the_ID(); ?>">
<div class="circle">
<div class="month"><?php the_time(d) ?></div>
<div class="year"><?php the_time('M Y');?></div>
</div>
<div class="thot">
<h4><?php the_title(); ?></h4>
<?php the_excerpt('Read More'); ?>
<hr />
</div>
</article>
<style>
.circle {
height: 165px;
width: 165px;
display: table-cell;
text-align: center;
vertical-align: middle;
border-radius: 50%;
background: white;
color:black;
line-height:35px;
}
.month{
font-size:60px;
font-weight:bold;
}
.year{
font-size:20px;
}
</style>
What is the best way to move the "thot" div next to the "circle" div?
("Cirle") [POST aka "thot div"]
Link http://ramovamusic.com/?page_id=165
Example: ramovamusic.com/example.jpg
So now that I understand your question. The problem is you have a set width on your article tag (500px) this needs to be increased so you can float your class circle and class thot. that way they will be next to each other.
Here is a working demo as to what I am talking about New Demo Working
Notice I removed the width on the article, added float right and width to class thot and float left on the circle. And now they are on the same line. You need to fiddle with it a bit to align it to your linking.
html:
<article style="" class="post" id="post-171">
<div class="circle">
<div class="month">20</div>
<div class="year">Mar 2015</div>
</div>
<div class="thot">
<h4>test 2</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce tellus urna, mollis in nibh nec, fermentum rhoncus lacus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus ante arcu, laoreet ut efficitur vel, ornare sed risus. Cras eget interdum erat, finibus facilisis justo. Nam lorem mi, laoreet at dui non, rutrum semper felis. <a class="read-more" href="http://ramovamusic.com/?p=171">Read More</a></p>
<hr />
</div>
</article>
css:
.circle {
height: 165px;
width: 165px;
display: table-cell;
text-align: center;
vertical-align: middle;
border-radius: 50%;
background: red none repeat scroll 0% 0%;
color: #000;
line-height: 35px;
float:left;
}
.thot{
float:right;
width:60%;
}
Add float:left to your circle div and some right margin, and for the .date class, add:
.date {
transform: translateY(-50%);
width: 165px;
top: 50%;
position: relative;
}
for .thot class add:
.thot {
float:left;
width: 300px; /* or whatever width works for you */
}
and finally you need to clear floats:
.post:after {
content: '';
display: table;
clear:both;
}
Here you go, better to apply the circle in a span to keep all the text together! Otherwise it can end up getting tricky like you saw!
https://jsfiddle.net/75tn8yps/3/
div{
float:left;
}
span.circle{
border: 1px solid red;
border-radius: 100%;
width: 100px;
height: 100px;
display: inline-block;
margin-left: 10px;
line-height: 95px;
text-align:center;
}
p{
text-align:center;
margin-top:40px;
}
Demo In Fiddle
I did change few things in the CSS File
.circle {
height: 165px;
width: 165px;
display: table-cell;
text-align: center;
vertical-align: middle;
color:white;
border-radius: 50%;
background: black;
color:black;
position:absolute;
}
.month{
font-size:40px;
font-weight:bold;
color:white;
line-height:90px;
}
.year{
font-size:20px;
color:white;
line-height:60px;
}
.thot{
border:1px solid black;
float:right;
width: calc(100% - 180px);
height:200px;
position:relative;
}
The new CSS. Check The fiddle.

Resources