I'm having an issue here where I constantly have an overflow-x whenever I set my side navigation off screen using translate. The real problem is that if I set an overflow-x:hidden; to all the ancestors div. It will stop my position sticky logo to work.
I've done my research and some of the following recommendation for fix was to add an overflow-x:hidden to the body itself and it would work. However it doesn't work in my case since there is a side navigation that is off screen.
The odd thing is that after adding overflow-x:hidden to the body. It fixes the overflow issue and the sticky logo is working but only on desktop mode. The moment I switch to mobile (Ctrl + Shift + M on Firefox and enable touch simulation), the overflow-x starts to scroll once again and the position sticky doesn't stick.
Here is a code snippet that I've found online in which I've added an additional side nav on the right so simulate my case.
HTML
<body>
<main>
<div class="overflow-x-hidden">
<h1>I want to be sticky!</h1>
<div class="sidenav"></div>
<div class="tall"></div>
</div>
</main>
</body>
CSS*
body {
overflow-x: hidden;
position: relative;
}
.overflow-x-hidden {
border: 1px solid blue;
}
h1 {
background: palevioletred;
color: #fff;
position: -webkit-sticky;
position: sticky;
top: 0;
}
.tall {
background: linear-gradient(to bottom, paleturquoise, white);
height: 300vh;
width: 100%;
}
.sidenav{
width: 250px;
height: 100%;
background: black;
position: absolute;
right: 0;
transform: translateX(100%)
}
Here are some of the similar issues that I've found.
Position sticky not working with body{ overflow-x: hidden; }
body { overflow-x: hidden; } breaks position: sticky
https://github.com/w3c/csswg-drafts/issues/865
https://bugzilla.mozilla.org/show_bug.cgi?id=1329203
For anyone struggling with this issue, I have similar issues and found a solution at https://stackoverflow.com/a/71268988/14151733.
Setting the overflow-x property to value clip helped me achieve
position sticky and prevent scrolling.
Here is more explanation in this article
CSS
.overflow-x-clip {
overflow-x: clip;
}
.sticky {
position: sticky;
top: 0;
}
HTML
<body class="overflow-x-clip">
<nav class="sticky">
...
</nav>
</body>
Related
I've set up a lightbox using only CSS and my images are longer than the viewport. The background is scrolling but the images won't.
Live site: https://hwestdesign.com
I've tried changing the overflow to various different settings and on different selectors and nothing is working. I'm really new to this and I don't know if I'm just making a simple mistake. I've read threads that have similar problems but the solutions provided aren't working either.
This is the CSS code I currently have active:
.thumbnail {
max-width: 100%;
}
.lightbox {
display: none;
width: 300px;
height: 300px;
overflow: scroll;
position: fixed;
top: 0;
left: 0;
z-index: 9999;
padding:10px;
text-align: center;
background: rgba(0,0,0,0.8);
}
.lightbox img{
max-width: none;
margin-top: 2%;
overflow-y: visible;
height: auto;
}
.lightbox:target {
outline: none;
display: block;
overflow: visible;
}
This is the HTML:
<div class="grid-item item1">
<img src="images/covers/hwest.jpg" class="thumbnail">
<img class="lightbox-content" src="images/hwestbranding.jpg">
</div>
When this loads the light box pops up and there is scrolling but it’s only the background underneath the light box that scrolls. The images are longer and I want to be able to scroll just the images vertically. Right now they are the right size but fixed. I’ve tried changing their position and the overflow but it does nothing
The combination of position:fixed and the overlay size is causing the issue. Setting an element to a fixed position removes it from the scroll context of the rest of the document. To resolve this you need to give the lightbox container a new scroll context by using the overflow property.
Note: you'll need to place the mouse cursor (pointer event) OVER the lightbox/modal specifically to cause the scroll. Otherwise, the "scroll" action will pass through to the document below
Here's an example:
And a link to codepen since its a bit difficult to see here.
body {
min-height:300vh;
background: url(https://images.unsplash.com/photo-1559291001-693fb9166cba) left top repeat;
}
.modal {
/* dark background overlay helps to position content */
position: fixed;
top:0; right:0; bottom:0; left:0;
background-color: rgba(0,0,0,0.6);
}
.modalInner {
/* put the white box in the right place */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* define how big it is before scrolling */
width: 80vw;
height: 80vh;
overflow-y: scroll;
/* look & feel */
background-color: #ffffff;
padding: 20px;
border: 1px solid #000;
}
<div class="modal">
<div class="modalInner">
<img src="https://images.unsplash.com/photo-1560010871-220685e68662" width="100%" />
</div>
</div>
EDIT/UPDATE: 7th June 2019
I've determined this is a bug in Safari, as the CSS works perfectly in all other browser. For anyone who finds this, if you're creating a sliding menu (which slides offscreen to the right of the viewport), as of Safari 12.1.1, adding overflow-x to the body tag will not work (it does work on Chrome, Firefox etc) - this means that when your menu div is positioned offscreen to the right, the user can scroll horizontally and see the menu.
I've found a (sort of) workaround is to give the parent container of the menu dive a position:fixed attribute - this obviously only works if you intend for your header to be fixed.
Original Question
I'm building a simple header with a menu that slides from right to left when the menu button is pressed. However, when I position the menu div offscreen (left: 100%), on Safari, I can scroll horizontally right to see the menu div. (No scroll bars appear, but I can scroll right via the Mouse)
If I set overflow-x:hidden on the header, then it hides the offscreen div, but also won't show it if you set the left:0 (ie. overflow-x seems to be hiding x and y directions).
Even more perplexing, if I change the header to position:fixed, then it works and you can't scroll right to see the offscreen menu div.
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.header {
width: 100%;
padding: 10px;
background: #CCC;
position: relative;
}
.slideMenu {
position: absolute;
top: 100%;
left: 100%;
width: 100%;
padding: 10px;
background: #666;
}
<div class="header">
Header ---> Scroll to Right
<div class="slideMenu">
Menu is visible offscreen- :(
</div>
</div>
Here's an example of the problem: https://jsfiddle.net/ar7qyfgt/
I ran into a similar issue with Safari. Solution that appears to be working is to apply overflow-x: hidden; to the html AND body tags.
Adding to body resolved issue in all browsers expect Safari. Applying it to both seems to do the trick with Safari while still supporting the other browsers.
I have the same issue in my Safari(Version 12.1.1) when I set my div to position: absolute and right: -15rem;
To fix it, I added a to include all elements within and have the CSS like this:
.wrapper {
position: relative;
overflow-x: hidden;
}
Hope this help.
What you currently have works, you just need to set overflow-x:hidden on the body instead of the .header
What are you trying to accomplish? This?:
JSFiddle: (https://jsfiddle.net/pzeqfb51/)
HTML:
<div class="header">
Header ---> Scroll to Right
<div class="slideMenu">
Menu is visible offscreen- :(
</div>
</div>
CSS:
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.header {
width: 100%;
padding: 10px;
background: #CCC;
position: relative;
}
.slideMenu {
position: absolute;
top: 100%;
left: 100%;
width: 100%;
padding: 10px;
background: #666;
}
div {
display:inline-block;
}
Let me first try to illustrate the problem
I have a webpage which contains a header and a sidenav. The sidenav is fixed in css, since I don't its content to move when scrolling.
When the page isn't scrolled down it works as intended, somewhat like this
However when I scroll i don't want whitespace on top of the sidenav. Currently when I scroll down the page, it looks somewhat like this
The intended behavior should be something like this
How do I go about this in css? Do I mess with the z-index of the elements? so the sidenav is behind the header when the page isn't scrolled? Or do I dynamically add to the sidenav's size when scrolling?
And how would either of these options be done in css?
As I understand, you have to set z-index of the header higher than the sidenav
Stack Snippet
.header {
height: 100px;
background: #000000;
position: relative;
z-index:999;
}
body {
margin: 0;
}
.sidebar {
position: fixed;
left: 0;
top: 0px;
width: 100px;
background: red;
height: 100%;
padding-top:100px;
}
.content {
height: 1000px;
background: yellow;
}
<div class="header"></div>
<div class="main">
<div class="sidebar"></div>
<div class="content"></div>
</div>
I have an element that I am making sticky with position sticky:
#header {
position: sticky;
width: 100vw;
top: 0;
}
<app-header id="header"></app-header>
And that works fine, but I realised that if I use:
body {
overflow-x: hidden;
}
That breaks sticky, and I need to set body overflow-x to hidden, how can I fix that, with only CSS solution, no JS solutions?
Setting the overflow-x property to value clip helped me achieve position sticky and prevent scrolling.
Here is more explanation in this article
UPDATE:
This has been successfully tested on Safari v12.0.2, Firefox v64.0, and Chrome v71.0.3578.98
Added position: -webkit-sticky; for Safari.
Unfortunately the spec is not too clear about the implications of overflow-x: hidden; on position sticky, but there is a way to fix this. Thankfully there is an issue to hopefully fix this: https://github.com/w3c/csswg-drafts/issues/865.
The simple solution is to remove or unset overflow-x: hidden; from every ancestor of the element you want to have position: sticky;. Then you can have overflow-x: hidden; on the body and it will work!
Also double check that you don't have overflow set on both the body and html tags which I posted about more in depth here: https://stackoverflow.com/a/54116725/6502003
Here is a pen if you want to play around with it: https://codepen.io/RyanGarant/pen/REYPaJ
/*
Try commenting out overflow on body style and uncommenting
overflow on .overflow-x-hidden class and you will see
position sticky stop working!
*/
body {
overflow-x: hidden;
}
.overflow-x-hidden {
/* overflow-x: hidden; */
border: 1px solid blue;
}
h1 {
background: palevioletred;
color: #fff;
position: -webkit-sticky;
position: sticky;
top: 0;
}
.tall {
background: linear-gradient(to bottom, paleturquoise, white);
height: 300vh;
width: 100%;
}
<div class="overflow-x-hidden">
<h1>I want to be sticky!</h1>
<div class="tall"></div>
</div>
The sticky doesn't work inside element with overflow: hidden or auto.
Refer to this https://developer.mozilla.org/en-US/docs/Web/CSS/position#sticky
A workaround can be working with this library
body, html { overflow-x: clip; }
This works well with position: sticky
Im using transform: translateX(-100px) for load animations and overflow-x:clip prevents expanding the viewport and showing horizontal scrollbar..
Not sure if this helps, but I struggled with this for mobile (where the page would "overflow" and scroll past the boundaries) for so long and finally fixed it.
I tried the body {overflow: hidden;} solution, but it would disable my sticky elements. So I then created a <div class="container"> that contained all of my other divs of the page inside the <body>, and that seemed to do it!
I just want to add this here if anyone runs into a similar issue. position:sticky was not working for me because we are applying overflow-y:scroll on tablet/mobile screen resolutions. overflow: and position:sticky do not work together. This article explains the 2 workarounds to fix it. I went with setting a fixed height on the table and then hiding the vertical scroll bar with
::-webkit-scrollbar {
width: 0;
background: transparent;
}::-webkit-scrollbar {
width: 0;
background: transparent; /*
}
This is how I make it work for me:
Create a parent wrapper/container element that should contains all your other page elements, and give it a fixed height (mostly height: 100vh) with overflow-y: auto and overflow-x: hidden as it's described in the code/snippet below ..
and make the body overflow: hidden to avoid any extra scroll bars ..
This solution may comes with some consequences/restrictions, for example:
if you're used to use the CSS scroll-behavior property in the html element you will need then to move it to the #page_wrapper element instead ..
body {
margin: 0;
overflow: hidden;
}
.page-wrapper {
height: 100vh;
overflow-y: auto;
overflow-x: hidden;
}
.sticky {
position: sticky;
left: 0;
padding: 4px;
text-align: center;
background-color: forestgreen;
}
.sticky-header {
top: 0;
}
.sticky-footer {
bottom: 0;
}
.long-content {
padding: 2rem;
min-height: 100vh;
}
.break-overflow-x {
min-width: 200vw;
padding: 2rem;
background-color: red;
}
<body>
<div class="page-wrapper">
<div class="sticky sticky-header"><button>Sticky Header</button></div>
<div class="long-content">Long vertical content</div>
<div class="break-overflow-x">Long horizontal content</div>
<div class="long-content">Long vertical content</div>
<div class="sticky sticky-footer"><button>Sticky Footer</button></div>
</div>
</body>
I think you have to fix :
body {
overflow-x: clip;
}
I hope this works .
can you try with the following...
#one { position: sticky; top: 10px; }* {
box-sizing: border-box;
}
body{overflow-x: hidden;}
dl > div {
background: #FFF;
padding: 24px 0 0 0;
}
dt {
background: #B8C1C8;
border-bottom: 1px solid #989EA4;
border-top: 1px solid #717D85;
color: #FFF;
font: bold 18px/21px Helvetica, Arial, sans-serif;
margin: 0;
padding: 2px 0 0 12px;
position: -webkit-sticky;
position: sticky;
top: -1px;
}
dd {
font: bold 20px/45px Helvetica, Arial, sans-serif;
margin: 0;
padding: 0 0 0 12px;
white-space: nowrap;
}
dd + dd {
border-top: 1px solid #CCC;
}
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/position -->
<dl>
<div>
<dt>A</dt>
<dd>Andrew W.K.</dd>
<dd>Apparat</dd>
<dd>Arcade Fire</dd>
<dd>At The Drive-In</dd>
<dd>Aziz Ansari</dd>
</div>
<div>
<dt>C</dt>
<dd>Chromeo</dd>
<dd>Common</dd>
<dd>Converge</dd>
<dd>Crystal Castles</dd>
<dd>Cursive</dd>
</div>
<div>
<dt>E</dt>
<dd>Explosions In The Sky</dd>
</div>
<div>
<dt>T</dt>
<dd>Ted Leo & The Pharmacists</dd>
<dd>T-Pain</dd>
<dd>Thrice</dd>
<dd>TV On The Radio</dd>
<dd>Two Gallants</dd>
</div>
</dl>
For those who have the same issue. I added overflow: hidden to the div below the header holding all the contents.
<div class="header" style="position: sticky;">
//navs
</div>
<div class="content-div" style="overflow: hidden;">
//contents
</div>
In my website I have two main divs - one for the banner at the top, and one for the main content. They both contain inner elements like imgs, iframes etc. but I don't think this is important for my problem which is: how can I make the scroll bar for the main content not overlap the banner?
If it helps, you can view the source for my actual website on my github. But to save wasting time looking, I've wrote a small snippet in html which demonstrates this issue:
document.getElementById("someText").innerText = "this is some content ".replace(/ /g, '\n').repeat(15);
html, body {
margin: 0;
padding: 0;
}
#header {
position: fixed;
background-color: teal;
z-index: 1;
top: 0;
height: 100px;
width: 100%;
}
#main {
postion: absolute;
top: 100px;
}
<body>
<div id="header">
header
</div>
<div id="main">
<pre id="someText"></pre>
</div>
</body>
It may be hard to see, in the snippet here on SO but the scroll bar on the right overlaps the banner and I what I want is for it to stop when it reaches the banner.
I have tried (in the CSS) setting the overflow of the body to hidden as this is the scroll bar overlapping the banner, but this just removes it entirely so I can't scroll - so clearly not what I am looking for...
I have also tried setting the overflow-y of the main div to scroll, but this does not work as a bar does appear where I want it, but it is grayed-out so not usable.
I have created a fiddle for you:
https://jsfiddle.net/3gvowvag/1/
Your HTML and JS stays the same. For your CSS:
html, body {
margin: 0;
padding: 0;
overflow-y: hidden;
}
#header {
position: fixed;
background-color: teal;
z-index: 1;
top: 0;
height: 100px;
width: 100%;
}
#main {
position: absolute;
top: 100px;
max-height: 100%;
width: 100%
overflow-y: scroll;
}
So the changes are basically to give your html, body a overflow-y: hidden and your #main a max-height and width of 100% as well as overflow-y: scroll.
This basically does what you want - though I wouldn't be 100% confident about setting up the page like that. Absolute positioning and offsetting via pixels is a bit oldschool, also setting the overflow-y to hidden for html/body, not exactly sure how those things will behave in the long term. But pretty hard to fully think of this without further context.
P.S.: awesome cat!
You just need to add overflow-y: hidden; to the body (take a look at this previous answer) and then apply overflow-y: scroll; to the #main div.
document.getElementById("someText").innerText = "this is some content ".replace(/ /g, '\n').repeat(30);
html, body {
margin: 0;
padding: 0;
}
body {
overflow-y: hidden;
}
#header {
position: fixed;
background-color: teal;
z-index: 1;
top: 0;
height: 100px;
width: 100%;
}
#main {
postion: absolute;
top: 100px;
overflow-y: scroll;
}
<body>
<div id="header">
header
</div>
<div id="main">
<pre id="someText"></pre>
</div>
</body>
You might find this easier with a flexbox layout. Maybe something like this. As example set the overflow to auto if you don't want to see the greyed out scroll bar
<div class="wrapper">
<div class="header">
header
</div>
<div class="content">
content
content
content
</div>
</div>
.wrapper{
display:flex;
flex-direction:column;
background:blue;
height: 100vw;
}
.header{
height:100px;
background-color:pink
}
.content{
background:green;
flex-grow: 1;
overflow:scroll;
}