Sticky sidebar on desktop and within content on mobile - html

Im having issues trying to create a sticky sidebar. On mobile the content just needs to flow within its container, then on desktop that div needs to break out into a sticky sidebar on the right, while the content flows on the left side as normal:
http://jsfiddle.net/sace510n/
Think its causing issues because the div for the sidebar is in the middle of each block.
.a {
position: sticky;
top: 0;
right: 0;
}
}
Any ideas would be greatly appreciated, thanks

Grid is the way to go here imho. Just create a new grid with 2 columns for your desktop inside your media query then set grid-column for the grey items to the left and the red one to the right. Then use position: sticky to, er, make it sticky.
The code should be self-explanatory but if not just drop me a comment on and I'll explain.
Edited: If each element is a different size, and the right-hand element is bigger than the first left-hand element then the gaps may look uneven. To solve this use a grid-row span on the .b class rule and choose a span that's big enough to keep the gaps even. Unfortunately grid-row: 1/-1 doesn't work on implicit grids.
body {
background: #20262e;
padding: 20px;
font-family: Helvetica;
}
.content {
display: grid;
gap: 1rem;
width: 100%;
max-width: 800px;
margin: 0 auto;
outline: 1px solid lime;
}
.a,
.b {
padding: 15px;
width: 200px;
height: 100px;
margin: 0 auto;
display: block;
}
.a {
background: grey;
}
.b {
background: red;
height: fit-content; /* added this during edit */
}
#media (min-width: 768px) {
.content {
grid-template-columns: repeat(2, 1fr);
}
.a {
grid-column: 1/2;
}
.b {
position: sticky;
top: 0;
grid-column: 2/3;
grid-row: 1/ span 3; /* <- choose a number to give the RHS grid enough space so the gaps of the LHS items don't grow */
}
}
.h0 {
height: 2.5rem;
}
.h1 {
height: 10rem;
}
.h2 {
height: 13rem;
}
.h3 {
height: 4rem;
}
<div class="content">
<div class="a h0">title1</div>
<div class="a">title2</div>
<div class="a">title3</div>
<div class="a">title4</div>
<div class="a h1">title5</div>
<div class="a h1">title6</div>
<div class="a">title7</div>
<div class="a h2">title8</div>
<div class="b">here on mobile, sticky sidebar on desktop <br/>title<br />title<br />title<br />title<br />title<br />title<br /></div>
<div class="a h1">title9</div>
<div class="a h3">title10</div>
</div>

Related

Issue with position sticky & bottom with different height flex children

I have a flex container with two children of different height.
The left item is shorter which I'm trying to make stick to the bottom while scrolling until the full container has been scrolled so they both align. Can't seem to get this to work. No parent overflows affecting this.
The desired behaviour is for the viewer(left) element to align at the top, scroll until it reaches the bottom, stick there until the full container (and side rail) has scrolled
Sandbox Here
.wrapper {
padding: 2rem;
background: lightgrey;
}
.container {
margin-inline: max(0px, ((100% - 1440px) / 2));
display: flex;
height: 2220px;
gap: 1rem;
> * {
border: 1px solid;
}
}
.viewer {
height: 1400px;
flex-grow: 3;
position: -webkit-sticky;
position: sticky;
bottom: 0;
background: white;
}
.side-rail {
height: 2190px;
flex-grow: 1;
background: white;
}
html,
body {
margin: 0;
}
<div class="wrapper">
<div class="container">
<div class="viewer">Viewer</div>
<div class="side-rail">Side rail</div>
</div>
</div>
Does making the the 'viewer' div
align-self: flex-end;
instead of flex-start do what you require ?
Seems like you have to make both the .viewer and the .side-rail of same height and overflow: auto the content within the side-rail

Cannot get full-width li's inline

I am trying to create a slider effect with a list of images. I need each one to by inline and take up with full screen width. I'm using float and also tried making the li's inline. The only thing that gets them on the same line is when they're not full width. How do I accomplish this while also having each li full-width of the screen? So they should extend past screen width.
Here is a screen shot of the current behavior:
https://www.awesomescreenshot.com/image/4177243/f8d1a38ce4b6096344f7f7befd4176fe
.mobile-slider-wrapper {
position: relative;
overflow: hidden;
width: 100%;
height: 600px;
}
.mobile-slider-wrapper ul {
position: relative;
margin: 0;
padding: 0;
height: 100%;
list-style: none;
}
.mobile-slider-wrapper li {
float: left;
display: inline;
margin: 0;
padding: 0;
list-style: none;
height: 100%;
width: 100%;
}
You can use a combination of the vw unit and a non-wrapping container to achieve this effect.
Here's a CSS mock up:
#container {
/* This stops the items wrapping over onto the next line */
white-space: nowrap;
/* We set the width and scroll to stop this container affecting the entire page's width */
overflow-x: auto;
width: 100vw;
/* This prevents any gaps between inline elements, keep in mind that if your child elements contain text, they will need to reset the font size, or this property can be removed */
font-size: 0;
}
.item {
display: inline-block;
width: 100vw; /* Make the item take up the full windows width*/
height: 100px;
}
.item1 {
background-color: #F00;
}
.item2 {
background-color: #0F0;
}
.item3 {
background-color: #00F;
}
.item4 {
background-color: #FF0;
}
<div id="container">
<div class="item item1"></div>
<div class="item item2"></div>
<div class="item item3"></div>
<div class="item item4"></div>
</div>
I think you'll need to use some JS to calculate the width on the wrapper. 2 slides = 200vw's, 3 slides = 300vw's, and so on.
$('.mobile-slider-wrapper').css('width', ($('.mobile-slider-wrapper').children().length * 100) + 'vw');

How to use overflow hidden on 1fr grid element

So I have this basic setup - a canvas area and an animator in a parent grid.
The parent grid is also inside another grid with one 1fr row.
I can resize the animator by dragging a resizer up and down.
canvas {
background-color: blue;
}
#grid1 {
grid-template-rows: 1fr;
}
#grid2 {
background-color: black;
display: grid;
grid-template-rows: 1fr auto;
overflow: hidden;
}
#canvas-area {
grid-row: 1;
background-color: red;
}
#animator {
grid-row: 2;
height: 200px;
}
<div id="grid1">
<div id="grid2">
<div id="canvas-area">
<canvas/>
</div>
<div id="animator"></div>
</div>
</div>
I want the canvas to be bigger than its parent and hide its overflow, but that seems to also expand the parent element.
I've already tried overflow: hidden, but that doesn't work
As a side question: I also noticed that there is a space of 4px under the canvas, why is that?
I want the canvas to be bigger than its parent and hide its overflow, but that seems to also expand the parent element.
Normally you'd add a height to the grid container so that the the 1fr in the grid-template-rows: 1fr auto is meaningful; otherwise the grid item auto-adjusts to the dimensions of its contents.
Add overflow: hidden to the grid item #canvas-area along with a fixed height to the container (say 400px as your previous jsFiddle had) - see demo below:
document.querySelector('button').onclick = () => {
document.querySelector('canvas').height = 300;
}
canvas {
background-color: blue;
}
#grid {
background-color: black;
display: grid;
grid-template-rows: 1fr auto;
width: 400px;
height: 400px; /* added a fixed height */
}
#canvas-area {
grid-row: 1;
background-color: red;
overflow: hidden; /* added */
}
#animator {
grid-row: 2;
height: 200px;
}
<div id="grid">
<div id="canvas-area">
<canvas/>
</div>
<div id="animator"></div>
</div>
<button>Change Canvas Height</button>
Note that adding min-height: 0 also does not grow the container:
document.querySelector('button').onclick = () => {
document.querySelector('canvas').height = 300;
}
canvas {
background-color: blue;
}
#grid {
background-color: black;
display: grid;
grid-template-rows: 1fr auto;
width: 400px;
height: 400px;
}
#canvas-area {
grid-row: 1;
background-color: red;
min-height: 0; /* added */
}
#animator {
grid-row: 2;
height: 200px;
}
<div id="grid">
<div id="canvas-area">
<canvas/>
</div>
<div id="animator"></div>
</div>
<button>Change Canvas Height</button>
Why so?
By default grid items have min-width: auto and min-height: auto (just like flex items). You can see some examples of of this behaviour below:
css-grid creates an imaginary column
How to make images stay within the rows of a css grid container?
and from the specs:
To provide a more reasonable default minimum size for grid items, this
specification defines that the auto value of min-width/min-height also
applies an automatic minimum size in the specified axis to grid items
whose overflow is visible and which span at least one track whose min
track sizing function is auto.
W3C
Space below canvas element?
I also noticed that there is a space of 4px under the canvas, why is that?
That is the whitespace, a characteristic of inline elements - you can remove that by making it a block element (add display: block) or adjusting vertical-align property (add vertical-align: top):
document.querySelector('button').onclick = () => {
document.querySelector('canvas').height = 300;
}
canvas {
background-color: blue;
display: block; /* added */
}
#grid {
background-color: black;
display: grid;
grid-template-rows: 1fr auto;
width: 400px;
height: 400px;
}
#canvas-area {
grid-row: 1;
background-color: red;
min-height: 0; /* added */
overflow: auto; /* added */
}
#animator {
grid-row: 2;
height: 200px;
}
<div id="grid">
<div id="canvas-area">
<canvas/>
</div>
<div id="animator"></div>
</div>
<button>Change Canvas Height</button>

Flex layout with a fixed column [duplicate]

This question already has answers here:
Is it possible for flex items to align tightly to the items above them?
(5 answers)
Make a div span two rows in a grid
(2 answers)
Closed 5 years ago.
I have this structure ... it's similar to the WordPress administration area ... the point is that I need .main taking all the space available in width and height and .foot remains down while there is no content that lowers it. I want to use flex because I will have columns inside the .main and I need these columns take full height as well... Maybe someone can give me another solution, but I can NOT change the html, only the CSS
.wrap {
display: flex;
}
.sidebar {
position: fixed;
top: 0;
bottom: -100px;
background-color: #00a0d2;
width: 200px;
}
.main {
background-color: #66BB6A;
display: flex;
}
.foot {
margin-left: -200px;
background-color: #9999dd;
height: 60px;
}
<div class="wrap">
<div class="sidebar">Menu</div>
<div class="main">Content</div>
<div class="foot">Footer</div>
</div>
where the final result would be something like this, thx
A fixed position sidebar will not be affected by flexbox, so you need to adjust your margins to make room for it.
html,
body {
height: 100%;
}
body {
min-height: 100%;
}
.wrap {
display: flex;
flex-direction: column; /* required to establish column layout */
min-height: 100%;
}
.sidebar {
position: fixed;
top: 0;
bottom: 0; /* full height - change if required */
background-color: #00a0d2;
width: 200px;
opacity: .5/* for demo purposes */
;
}
.main {
background-color: #66BB6A;
display: flex;
flex: 1; /* take remaining height*/
margin-left: 200px; /* width of sidebar */
}
.foot {
margin-left: 200px; /* width of sidebar */
background-color: #9999dd;
height: 60px;
}
<div class="wrap">
<div class="sidebar">Menu</div>
<div class="main">Content</div>
<div class="foot">Footer</div>
</div>
You could use css grid. It allows room for 2d grid with minimal code.
.wrap {
display: grid;
/*Make 2 columns with the first having a min width of 200px*/
grid-template-columns: minmax(200px, 1fr) 10fr;
}
.sidebar {
background-color: #00a0d2;
/*Make sidebar take up the space of the 2 rows*/
grid-row: 1/3;
}
.main {
background-color: #66BB6A;
/*Let the main content take up the space of view height*/
height: 100vh;
}
.foot {
/*set footer to span the last row leaving the space for the sidebar*/
grid-column: 2/3;
background-color: #9999dd;
height: 60px;
}
<div class="wrap">
<div class="sidebar">Menu</div>
<div class="main">Content</div>
<div class="foot">Footer</div>
</div>

Filling content background till it reaches footer

I have similar problem which can be found here. But i couldn't make it work or i didnt understand it fully.
My problem which im trying to resolve is - I want my content background to reach footer even if there isnt enough content to be displayed. I created a simple fiddle which can be found here. As you can see there isnt enough content to reach footer and there is this "blue" space between content and footer. I would like to make that space grey.
HTML :
<div class=blue>header here</div>
<p>LOGO here</p>
<div class="blue">navigation bar here</div>
<div class="content">
No content.
</div>
<div class="footer">footer is here</div>
CSS:
.blue {
color: #ffffff;
background-color: #294a70;
display: block;
float: none;
width: 400px;
margin: 0 auto;
text-align: center;
}
p {
text-align: center;
color: #ffffff;
}
.content {
background-color: #e6e6e6;
display: block;
float: none;
margin: 0 auto;
overflow:hidden;
width:400px;
margin-bottom:30px;
}
.footer {
color: #ffffff;
background-color: #294a70;
display: block;
float: none;
width: 400px;
margin: 0 auto;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height:30px;
}
body {
margin:0;
padding:0;
font-family: 'Open Sans', sans-serif;
line-height: 1.5;
font-size: 14px;
overflow-x:hidden;
background-image:url('http://www.planwallpaper.com/static/images/Alien_Ink_2560X1600_Abstract_Background_1.jpg');
min-height: 100%;
}
html {
position:relative;
min-height: 100%;
}
All help will be appreciated!
Use CSS3 calc() function
the trick is, if you know the height of header & footer, you can use this function with vh units, 100vh gives you screen height, just substract the height of hearder & footer from it.
E.g.
If header is 80px & Footer is 40px, i.e. total 120px, then use
.content{
min-height: calc(100vh - 120px);
}
The purpose of using min-height is if content is not present then atleast this height is applied, but if there is more content than screen then div is expanded to fit accordingly.
Updated JSFiddle:
https://jsfiddle.net/vj07e8g1/5/
You could try a flexbox layout instead:
HTML
<body>
<header></header>
<main class="content"></main>
<footer></footer>
</body>
CSS
body {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main.content {
flex: 1;
}
Check out this codepen example: http://codepen.io/StefanBobrowski/pen/zZXXWy
You can add this to your content style:
min-height:400px;
It'll push the footer a little, but it'll do the work.
Hope this is what you're looking for.
The easiest contemporary way, depending on your browser-support requirements, would be to use CSS grids, which allows you to define rows and columns and assign certain content to be in specific places (placed by grid-row and grid-column), like follows:
html,
body {
height: 100%;
}
/* to force all elements to be sized including
their padding and border-widths */
body,
::before,
::after {
box-sizing: border-content;
}
body {
/* To use CSS grid, forcing the child elements of
the <body> element to adopt 'display: grid-item': */
display: grid;
/* defining the three columns of the grid, the first and
third being equal fractions of the space left over after
the second (middle) column's width of 400px is calculated */
grid-template-columns: 1fr 400px 1fr;
/* reducing the first three rows to the minimum height needed
to fully display their content, setting the fourth row
to take up the remaining unoccupied space once the other
heights are calcuated and setting the final row's height to
30px: */
grid-template-rows: min-content min-content min-content 1fr 30px;
height: 100vh;
background-image: url(https://i.stack.imgur.com/2oC8H.jpg);
}
body>* {
/* setting all the child elements of the <body> to be placed
in grid-column 2 (the central 400px-wide column): */
grid-column: 2;
}
/* Setting the default shared styles of the .blue elements: */
.blue {
color: #ffffff;
background-color: #294a70;
}
.blue.header {
/* positioning this element in the first (one-based counting)
row: */
grid-row: 1
}
body>p {
grid-row: 2;
}
.blue.navigation {
grid-row: 3;
}
div.content {
grid-row: 4;
/* background-color purely to show that the space of the
div.content element occupies the full space available: */
background-color: #ffa;
}
div.footer {
grid-row: 5;
}
<div class="header blue">header here</div>
<p>LOGO here</p>
<div class="blue navigation">navigation bar here</div>
<div class="content">
No content.
</div>
<div class="footer">footer is here</div>
JS Fiddle.
Please note that I did add a class-name to both the .blue elements in order to more-easily distinguish them according to their roles in the document, and from each other when placing them in the document.