What's the difference between `overflow` properties `overlay` and `scroll`
Scroll will always show scroll bars irrespective of if the content is being clipped or not.
Overlay was a webkit proprietary property but is now depreciated. It does the same thing that auto does. Which is display a scroll bar when necessary.
Just as a side note the current possible values for overflow are
auto
hidden
scroll
visible
Great article here by css tricks documenting the difference.
https://css-tricks.com/the-css-overflow-property/
Overflow: overlay doesn't work in firefox
Possible values for overflow are:
visible
hidden
auto
scroll
See here or here for a discussion of these.
Using any other value in different browsers will yield unpredictable results as they handle the incorrect value differently.
Edit: Following the comment, I've managed to find mention of overflow:overlay here.
overlay is described as:
Content is clipped and scroll bars are added when necessary.
Importantly its also said only to work in Safari or Chrome (ie WebKit).
This item on WebKit bugzilla suggest it is not long for this world in any case:
WebKit currently has a proprietary CSS overflow value called "overlay" which is undocumented and as far as I can tell from reading the code works exactly like "auto".
We should either remove it or rename it to "-webkit-overlay".
Update March 2016
Looks like overflow: overlay
hasn't gone away. There are signs of it working it's way into the standards.
The difference between overlay
and auto
would only be that the scrollbars would appear over the top of the page content, and not cause it to take layout space.
See here for the discussion.
Prevent body scrolling but allow overlay scrolling
Theory
Looking at current implementation of the pinterest site (it might change in the future), when you open the overlay, a noscroll
class is applied to the body
element (setting overflow: hidden
) making the body
no longer scrollable.
The overlay created on-the-fly or already injected in the page and made visible via display: block
— it makes no difference – has position : fixed
and overflow-y: scroll
, with top
, left
, right
and bottom
properties set to 0
: this style makes the overlay fill the whole viewport (but now we are in 2022, so you may use inset: 0
instead).
The div
inside the overlay is in position: static
so the vertical scrollbar is related to that element. This is resulting in a scrollable but fixed overlay.
When you close the overlay, you have to hide it (using display: none
) and you could even remove the node via javascript (or just the content inside, it's up to you but also depends on the nature of the content).
The final step is to also remove the noscroll
class applied to the body
(so the overflow
property gets back to the value it had previously)
Code
Codepen Example
(it works by changing the aria-hidden
attribute of the overlay in order to show and hide it and to increase its accessibility).
Markup
(open button)
<button type="button" class="open-overlay">OPEN LAYER</button>
(overlay and close button)
<section class="overlay" aria-hidden="true" tabindex="-1">
<div>
<h2>Hello, I'm the overlayer</h2>
...
<button type="button" class="close-overlay">CLOSE LAYER</button>
</div>
</section>
CSS
.noscroll {
overflow: hidden;
}
.overlay {
position: fixed;
overflow-y: scroll;
inset: 0; }
[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }
Javascript (vanilla-JS)
var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]'),
openingBtt;
[].forEach.call(overlayBtts, function(btt) {
btt.addEventListener('click', function() {
/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';
/* storing a reference to the opening button */
if (overlayOpen) {
openingBtt = this;
}
/* Toggle the aria-hidden state on the overlay and the
no-scroll class on the body */
overlay.setAttribute('aria-hidden', !overlayOpen);
body.classList.toggle('noscroll', overlayOpen);
/* On some mobile browser when the overlay was previously
opened and scrolled, if you open it again it doesn't
reset its scrollTop property */
overlay.scrollTop = 0;
/* forcing focus for Assistive technologies but note:
- if your modal has just a phrase and a button move the
focus on the button
- if your modal has a long text inside (e.g. a privacy
policy) move the focus on the first heading inside
the modal
- otherwise just focus the modal.
When you close the overlay restore the focus on the
button that opened the modal.
*/
if (overlayOpen) {
overlay.focus();
}
else {
openingBtt.focus();
openingBtt = null;
}
}, false);
});
/* detect Escape key when the overlay is open */
document.body.addEventListener('keyup', (ev) => {
if (ev.key === "Escape" && overlay.getAttribute('aria-hidden') === 'false') {
overlay.setAttribute('aria-hidden', 'true');
body.classList.toggle('noscroll', false);
openingBtt.focus();
openingBtt = null;
}
})
Finally, here's another example in which the overlay opens with a fade-in effect by a CSS transition
applied to the opacity
property. Also a padding-right
is applied to avoid a reflow on the underlying text when the scrollbar disappears.
Codepen Example (fade)
CSS
.noscroll { overflow: hidden; }
@media (min-device-width: 1025px) {
/* not strictly necessary, just an experiment for
this specific example and couldn't be necessary
at all on some browser */
.noscroll {
padding-right: 15px;
}
}
.overlay {
position: fixed;
overflow-y: scroll;
inset: 0;
}
[aria-hidden="true"] {
transition: opacity 1s, z-index 0s 1s;
width: 100vw;
z-index: -1;
opacity: 0;
}
[aria-hidden="false"] {
transition: opacity 1s;
width: 100%;
z-index: 1;
opacity: 1;
}
CSS overflow-x: visible; and overflow-y: hidden; causing scrollbar issue
After some serious searching it seems i've found the answer to my question:
from: http://www.brunildo.org/test/Overflowxy2.html
In Gecko, Safari, Opera, ‘visible’
becomes ‘auto’ also when combined with
‘hidden’ (in other words: ‘visible’
becomes ‘auto’ when combined with
anything else different from
‘visible’). Gecko 1.8, Safari 3, Opera
9.5 are pretty consistent among them.
also the W3C spec says:
The computed values of ‘overflow-x’
and ‘overflow-y’ are the same as their
specified values, except that some
combinations with ‘visible’ are not
possible: if one is specified as
‘visible’ and the other is ‘scroll’ or
‘auto’, then ‘visible’ is set to
‘auto’. The computed value of
‘overflow’ is equal to the computed
value of ‘overflow-x’ if ‘overflow-y’
is the same; otherwise it is the pair
of computed values of ‘overflow-x’ and
‘overflow-y’.
Short Version:
If you are using visible
for either overflow-x
or overflow-y
and something other than visible
for the other, the visible
value is interpreted as auto
.
How to implement multiple fullscreen overlays in HTML?
A way you can do this is by giving your overlays classes with which you can select them from JavaScript. Give each overlay a unique id to identify it with.
<div class="overlay js-overlay" id="overlay-one" hidden>
...
</div>
Now you buttons should also have a class to identify them with. Give your button a value
attribute in which you set the id
of the overlay that the button belongs to.
<button class="js-overlay-trigger" type="button" value="overlay-one">Open overlay</button>
Now in JavaScript. Select all buttons with document.querySelectorAll
. Loop over each button and add an event listener to it. This is (almost) the same as an onclick
attribute, but you gives you much more flexibility and imo should be used in favor of the inline attribute.
Create a function that reads the value
of the clicked button, this contains the id
of the overlay we need. Select the element from the document based on the value in the value
property. If the overlay is found, then the overlay will be shown.
const triggers = document.querySelectorAll('.js-overlay-trigger');
function showOverlay(event) {
const selector = event.target.value;
const overlay = document.getElementById(selector);
if (overlay !== null) {
overlay.hidden = false;
}
}
for (const trigger of triggers) {
trigger.addEventListener('click', showOverlay);
}
This example uses the hidden
attribute and property to show overlay. But you can also add or remove CSS classes to get the same behavior. The style
property should be used as a last resort.
Edit
The closing of the overlays is done almost in the same manner. First you select all the overlays. Loop over each overlay and attach an event listener. The function attached to the event should hide the currently clicked overlay.
const overlays = document.querySelectorAll('.js-overlay');
function closeOverlay(event) {
const overlay = event.currentTarget;
overlay.hidden = true;
}
for (const overlay of overlays) {
overlay.addEventListener('click', closeOverlay);
}
Javascript transitions overlay & opacity
in your css change width
property to 100%
and add display
property with none
value and remove transition
property.
then if you want to use javascript try this code:
function fadeIn(fadeTarget) {
var op = 0.01;
fadeTarget.style.opacity = op;
fadeTarget.style.display = 'block';
var fadeEffect = setInterval(function () {
fadeTarget.style.opacity = op;
if (op < 1) {
op += 0.01;
fadeTarget.style.opacity = op;
} else {
clearInterval(fadeEffect);
}
}, 10);
}
function fadeOut(fadeTarget) {
var op = 1;
fadeTarget.style.opacity = op;
var fadeEffect = setInterval(function () {
if (fadeTarget.style.opacity > 0) {
fadeTarget.style.opacity -= 0.01;
} else {
clearInterval(fadeEffect);
fadeTarget.style.display = 'none';
}
}, 10);
}
function openNav() {
fadeIn(document.getElementById("myNav"));
}
/* Close when someone clicks on the "x" symbol inside the overlay */
function closeNav() {
fadeOut(document.getElementById("myNav"));
}
and if you want use jquery , remove onload
attribute and add closeButton
and searchButton
id to tags.
$(document).ready(function(){
$("#closeButton").click(function(){
$("#myNav").fadeOut();
});
$("#searchButton").click(function(){
$("#myNav").fadeIn();
});
});
/* The Overlay (background) */
.overlay {
/* Height & width depends on how you want to reveal the overlay (see JS below) */
height: 100%;
width: 100%;
display:none;
position: fixed; /* Stay in place */
z-index: 999; /* Sit on top */
left: 0;
top: 0;
background-color: rgb(0,0,0); /* Black fallback color */
background-color: rgba(0,0,0, 0.85); /* Black w/opacity */
overflow-x: hidden; /* Disable horizontal scroll */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<span id="searchButton" style="cursor:pointer">
<img class="logo" src="https://cdn2.iconfinder.com/data/icons/font-awesome/1792/search-64.png" onerror="this.onerror=null; this.src='img/global/logo.png'" alt="searchsite" />
</span>
<!-- The overlay -->
<div id="myNav" class="overlay">
<!-- Button to close the overlay navigation -->
<span class="closebtn" style="cursor:pointer" id="closeButton">×</span>
<!-- Overlay content -->
<div class="overlay-content">
<form id="searchbox" action="http://englishclass.dk/pages/results.html" autocomplete="off">
<input value="015532613638252232237:nvc8fxndlgb" name="cx" type="hidden" />
<input id="q" name="q" size="70" type="text" placeholder="Search the English Class Website..." />
<input value="Search" name="sa" autofocus type="submit" id="submit" style="background-image: url('../_themes/englishclass/img/searchsmall.png')" ;/>
</form><span class="sexy_line"></span>
</div>
</div>
Related Topics
How to Disable Automatic Links Coloring Without Selecting a Color
Tweaking Bootstrap 2.0 for Semantic Markup
How to Alias Class Name in CSS or SASS
Ie11 Triggers CSS Transition on Page Load When Non-Applied Media Query Exists
What Browsers Support "!Important"
Flexbox, Min-Height, Margin Auto and Internet Explorer
Bootstrap 4 Pull-Xs-Right Not Working as Expected
What Are the Differences Between Display:Box and Display:Flexbox
Bootstrap 4 Invalid Feedback with Input Group Not Displaying
Change Color of Select Component's Border and Arrow Icon Material Ui
Angular 2 Animation VS CSS Animation - When to Use What
Bootstrap 4 Responsive Button Size
Anyway to Have a Label Respond to :Focus CSS