Pure CSS overlay scrolling - javascript

using only css and html, is it possible to scroll away the inner div (overlay red div) completely before scrolling down the rest of the page? Essentially, wondering if overlay scrolling while freezing the behind div is possible in only css? Then once the red div is gone, unfreeze the background scrolling and continue on. Similar to this site here: https://humaan.com/ . Or would some sort of JavaScript need to be used?
.headervideo{background-color:blue; width:100%; height:900px;}
.headerbreak{width:100%; height:300px;}
.headervideo #inner-box {
background-color: red;
height: 90%;
width: 100%;
}
<div class="headervideo">
<div id="inner-box"></div>
</div>
<div class="headerbreak">
<div>

position:sticky can approximate this:
.headervideo {
background: url(https://picsum.photos/id/1064/800/800) center/cover;
height: 100vh;
position: relative;
z-index: 2;
}
.nextsection {
background: url(https://picsum.photos/id/107/800/800) center/cover;
height: 100vh;
margin-top: -100vh;
position: sticky;
top: 0;
}
.container {
height:200vh;
}
body {
margin: 0;
}
<div class="container">
<div class="headervideo"></div>
<div class="nextsection"></div>
</div>
<div style="height:150vh"> more content later </div>

With CSS, you could use the hover event to detect a certain scroll position (e.g. on something just after the red div), but this would not work on touch only devices like mobile phones. It also wouldn't be reliable, as the cursor could be anywhere on the screen.
Using JavaScript to detect scroll position would be necessary. However, you could use the JavaScript only to add a class at different scroll positions and then do the rest with CSS. Here's a simple example:
var red = document.querySelector('#inner-box');
var begin = red.scrollTop;
var end = begin + red.clientHeight;
console.log(begin)
document.body.classList.add('in');
window.addEventListener("scroll", (event) => {
if(this.scrollY < begin) {
document.body.classList.add('before');
document.body.classList.remove('after');
document.body.classList.remove('in');
} else if(end < this.scrollY) {
document.body.classList.remove('before');
document.body.classList.add('after');
document.body.classList.remove('in');
} else {
document.body.classList.remove('before');
document.body.classList.remove('after');
document.body.classList.add('in');
};
});
.headervideo {
background-color: blue;
width: 100%;
height: 900px;
}
.headerbreak {
width: 100%;
height: 300px;
}
.headervideo #inner-box {
background-color: red;
height: 90%;
width: 100%;
}
body {
}
body.before {
background-color: lightgreen;
}
body.in {
background-color: lightpink;
}
body.after {
background-color: lightblue;
}
<body>
<div class="headervideo">
<div id="inner-box"></div>
</div>
<div class="headerbreak">
<div>
</body>

Related

How to bring sidebar top of header while both as fixed position?

HTML Code:
<div id="screenLeft" class="screen"></div>
<div id="screenTop" class="screen"></div>
<div id="container">
<div id="content">
Test Possition of Text and whatnot1<br />
Test Possition of Text and whatnot2<br />
Test Possition of Text and whatnot3<br />
Test Possition of Text and whatnot4<br />
</div>
</div>
CSS code:
.screen {
position: fixed;
background: black;
}
#screenTop {
height: 100px;
width: 100%;
background: green;
}
#screenLeft {
height: 100%;
width: 100px;
}
#screenTop { top: 0; }
#screenLeft { left: 0; }
#content {
margin: 100px;
}
I have two Questions
how can I bring black sidebar on top of header while both is fixed?
How can I show content div in whole screen if sidebar & header display is none?
enter image description here
First question:
How can I show sidebar on top of header while both are positioned fixed?
simple answer, you can use z-index = number (z-index = 100 for example),
reference: MDN
The z-index CSS property sets the order of a positioned element and its descendants. Overlapping elements with a larger z-index cover those with a smaller one.
example code:
.screen {
position: fixed;
start: 0;
}
#screenTop {
height: 100px;
width: 100%;
top: 0;
z-index:10;
}
#screenLeft {
height: 100%;
width: 100px;
top:100px; /*To Prevent Overlapping*/
z-index:9;
}
#content{
margin: 50px;
}
Second question:
How can I show content div in whole screen if sidebar & header display is none?
You will need to use a little javascript to perform this,
Add the following code before the end of your <body> tag,
then modify it for your needs.
<script>
function ToggleContent()
{
let screenTopDisplay = document.getElementById("screenTop").style.display;
let screenLeftDisplay = document.getElementById("screenLeft").style.display;
let toggleMargin =
(screenTopDisplay = "" || screenTopDisplay = "block") && (screenLeftDisplay = "" || screenLeftDisplay = "block");
let container = document.getElementById("container");
if(toggleMargin)
{
container.style.margin = "100px 0px 0px 100px";
}
else
{
container.style.margin = "0px";
}
}
</script>
*remember to call the function when you show/hide the .screen ToggleContent()
For your first Question add these 2 properties top:0px;(to start form to 0 of screen) and z-index:99; (to stack over the topbar) to sidebar id #screenLeft
For your 2nd Question after removing sidebar and top bar add this css
#content { margin-left: 0; margin-top: 0; }
it will remove margin form content div.
.screen {
position: fixed;
background: black;
}
#screenTop {
height: 100px;
width: 100%;
background: green;
}
#screenLeft {
height: 100%;
width: 100px;
top:0;
z-index:99;
}
#screenTop { top: 0; }
#screenLeft { left: 0; }
#content {
margin: 100px;
}
<div id="screenLeft" class="screen"></div>
<div id="screenTop" class="screen"></div>
<div id="container">
<div id="content">
Test Possition of Text and whatnot1<br />
Test Possition of Text and whatnot2<br />
Test Possition of Text and whatnot3<br />
Test Possition of Text and whatnot4<br />
</div>
</div>

How to set element to grow horizontally instead of breaking to a new line?

I'm facing problem with breaking the line on website. What do I mean?
HTML code
<main class="clearfix">
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
With such HTML code I'd like to have:
fixed height on main element (for example 80vh)
fixed height for all the elements first and third 40vh + second 80vh
fixed width for first and third element 50vw
fluid width for second element - but this is main problem - second element has to be in the same place and grow horizontally (to create scroll on the bottom of the site)
Please find my codepen
I've added button that'll add pixels to second element - but it destroys my website.
I'm not sure if flexbox is better than floats.
I'll appreciate any tip.
Here is the snippet:
let counter = 0;
document.querySelector("button").addEventListener("click", function() {
document.querySelector(".second").style.width = `calc(50% + ${counter}px)`;
console.log(counter);
counter++;
});
* {
padding: 0;
margin: 0;
}
main {
max-height: 80vh;
}
.first,
.third {
height: 40vh;
width: 50vw;
background-color: black;
float: left;
}
.third {
background-color: red;
}
.second {
height: 80vh;
width: 50%;
float: right;
background-color: blue;
}
.clearfix::after {
content: "";
display: table;
clear: both;
}
<main class="clearfix">
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
I would suggest you to go with position properties. Since you have a little difference between the order of your DOM element and their visual representation, like 1,2,3 in the DOM, but visually it's more like 1,3,2.
However, in such situation float is your enemy. I'm not 100% sure about flex, AFAIK flex would keep all the elements inside the parent element and prevent the scrolling.
If you go with absolute positioning, (since you already have the heights and widths defined)
Apply:
position: relative to the main element, it will be the base point of the child elements if they are set to absolute.
overflow-x: scroll to the main element. it will allow you to scroll horizontally when you increase the width of your second element.
position: absolute on .first, .second, .third, as you have the height and width defined, now set their position accordingly, check the snippet, you'll get it.
Finally you're good to add more value to your width of the target element.
Tip: always keep a consistency in your css units, for example, if used vh / vw use this for similar elements at least, or if px / em / rem is used, try to use the same accordingly.
Check the snippet in full page mode
let counter = 0;
document.querySelector("button").addEventListener("click", function() {
document.querySelector(".second").style.width = `calc(50vw + ${counter}vw)`;
document.querySelector("#added").textContent = counter;
counter++;
});
* {
padding: 0;
margin: 0;
}
main {
overflow-x: scroll;
position: relative;
min-height: 80vh;
}
.first,
.third {
height: 40vh;
width: 50vw;
background-color: black;
position: absolute;
left: 0;
top: 0;
}
.third {
background-color: red;
top: 40vh;
}
.second {
height: 80vh;
width: 50vw;
background-color: blue;
position: absolute;
left: 50vw;
top: 0;
}
button {
margin: 30px 5px;
border: 1px solid #cecece;
padding: 5px 10px;
}
<main>
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
<p><span id="added">0</span>vw Added to blue div's width</p>

Detect When Mouse Enters Specific Area of Document (Not a Div Element)

I'm trying to figure out how Medium made their bottom action / menu bar slide up when your mouse enters the bottom of the document. The slide up effect is not triggered by moving the mouse over the invisible div (it slides up & down via transform translateY).
Besides, the menu bar is only 44px in height, but its is-visible class gets triggered way before your mouse is near it — but by what? When using Inspect Element, I can't see any hidden divs that could be triggering it..
I've searched for countless of ways, e.g. "show element when mouse enters specific part of document" but all search results involve when the mouse enters or moves over a div element, which is not the solution I'm looking for.
Obviously, you can solve this problem by putting the slide up menu inside a hidden container like I've done here, and then you get the desired result:
(function() {
var actionBar = document.querySelector('.action-bar');
var actionBarWrapper = document.querySelector('.action-bar-detection');
function showDiv() {
actionBar.classList.add('js-is-visible')
}
function hideDiv() {
actionBar.classList.remove('js-is-visible')
}
actionBarWrapper.onmouseover = showDiv;
actionBarWrapper.onmouseout = hideDiv;
})();
* {
margin: 0;
padding: 0;
box-sizing: border-box;
line-height: 1.5;
}
body {
height: 100%;
}
.wrapper {
width: 90%;
max-width: 600px;
margin: 5% auto;
}
.action-bar {
position: absolute;
left: 0;
bottom: 0;
border: 1px solid #252321;
background: #fff;
padding: 16px;
width: 100%;
min-height: 50px;
opacity: 0;
transform: translateY(100%);
transition: all .5s;
z-index: 99;
}
.action-bar-detection {
height: 150px;
width: 100%;
opacity: 1;
position: fixed;
bottom: 0;
left: 0;
z-index: 1;
}
.js-is-visible {
opacity: 1;
transform: translateY(0%);
}
<html>
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<div class="wrapper">
<p>When mouse enters the hidden action bar element, slides up.</p>
<p>But it's only happening because the action-bar is inside an invisible detection layer class (action-bar-detection) with a height of 150px.</p>
</div>
<div class="action-bar-detection">
<div class="action-bar">
Bottom Menu
</div>
</div>
</body>
</html>
However, this doesn't seem to be what Medium have done, and if this can be done without adding more HTML & CSS, I want to learn how! :-)
I think I'm not phrasing the problem correctly, since I can't find any solutions even remotely close (I've searched A LOT).
Any advice? What should I read up on? :-)
Get height of viewport, track onmousemove, and compare clientY from the mouse event to the viewport height:
(function() {
var actionBar = document.querySelector('.action-bar');
var viewHeight = window.innerHeight - 150;
function toggleDiv(e) {
if (e.clientY >= viewHeight) {
actionBar.classList.add('js-is-visible');
} else {
actionBar.classList.remove('js-is-visible');
}
}
window.onmousemove = toggleDiv;
})();
* {
margin: 0;
padding: 0;
box-sizing: border-box;
line-height: 1.5;
}
body {
height: 100%;
}
.wrapper {
width: 90%;
max-width: 600px;
margin: 5% auto;
}
.action-bar {
position: absolute;
left: 0;
bottom: 0;
border: 1px solid #252321;
background: #fff;
padding: 16px;
width: 100%;
min-height: 50px;
opacity: 0;
transform: translateY(100%);
transition: all .5s;
z-index: 99;
}
.action-bar-detection {
height: 150px;
width: 100%;
opacity: 1;
position: fixed;
bottom: 0;
left: 0;
z-index: 1;
}
.js-is-visible {
opacity: 1;
transform: translateY(0%);
}
<div class="wrapper">
<p>When mouse comes within 150px of the bottom part of the screen, the bar slides up.</p>
<p>When the mouse leaves this defined area of the screen, the bar slides down.</p>
</div>
<div class="action-bar-detection">
<div class="action-bar">
Bottom Menu
</div>
</div>
You could do this by listening to the mousemove event on the document, you will want to invest effort into making this performant as it will be triggered frequently. The most common way to regulate events like this is through throttling.
Once you are hooked into the mousemove event you will need to get the Y coordinate of the cursor and compare that to the height of the window, if it is within a threshold then you can reveal your panel, once it moves out you can proceed to hide it again.
Here is an example showing a basic implementation jsFiddle
// Using underscore for the throttle function though you can implement your own if you wish
document.addEventListener('mousemove', _.throttle(mouseMoveEventAction, 200));
function mouseMoveEventAction(e) {
doPanelStuff(isInsideThreshold(e.clientY));
}
function doPanelStuff(isActive) {
var panelElement = document.querySelector('.panel');
if (isActive) {
panelElement.style.background = 'red';
} else {
panelElement.style.removeProperty('background');
}
}
function isInsideThreshold(cursorY) {
var threshold = 200;
var clientHeight = document.documentElement.clientHeight;
return cursorY > (clientHeight - threshold);
}
html, body {
height: 100%;
}
.container, .content {
height: 100%;
width: 100%;
}
.panel {
height: 50px;
position: absolute;
bottom: 0;
width: 100%;
background: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<div class="container">
<div class="content"></div>
<div class="panel"></div>
</div>

Using pure CSS, make a div centered until it runs into sidebar from resizing the window?

I want to create a website with a single fixed-width centered column and an additional fixed-width sidebar that is position: fixed on the left. When the window is large, this works perfectly, but when I resize the window, they begin to overlap when there's plenty of room left on the right side of the window. For example:
I'd like the center div to be positioned in the center until it runs into the sidebar, at which point I'd like it to have a more fluid responsive design, where the sidebar starts to push the div to the right as you resize the window. For example:
The only solution I'm aware of is something like this (using the jQuery resize event and adding a class to the center column when the window resizes small enough):
var SMALL_WINDOW_SIZE = 560;
function checkWindowSize() {
var $content = $("#content");
if ($(this).width() < SMALL_WINDOW_SIZE && !$content.hasClass("smallWindow")) {
$content.addClass("smallWindow");
} else if ($(this).width() >= SMALL_WINDOW_SIZE && $content.hasClass("smallWindow")) {
$content.removeClass("smallWindow");
}
}
$(document).ready(function() {
checkWindowSize();
});
$(window).resize(function() {
checkWindowSize();
});
#sidebar {
background: orange;
width: 100px;
height: 200px;
position: fixed;
top: 10px;
left: 10px;
}
#content {
background: blue;
width: 300px;
height: 350px;
margin: 0px auto;
}
.smallWindow {
float: left;
margin-left: 120px !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id='sidebar'></div>
<div id="content"></div>
I can't help but feel there should be a pure CSS solution or one that uses less or more elegant JavaScript. Is there such a thing?
This isn't by any means the best way of achieving the desired effect with CSS, but it's the methodology behind using CSS media queries to adapt layout that I want to convey.
Obviously if this meets your needs, you'll want to adjust the numbers/widths to suit your case.
*, :before, :after{
box-sizing: border-box;
}
body {
margin: 0;
}
.wrapper {
position: relative;
padding: 20px;
}
.sidebar, .main {
padding: 20px
}
.sidebar {
position: fixed;
top: 20px;
left: 20px;
width: 200px;
background: goldenrod;
color: white;
height: 50vh;
}
.main {
margin-left: 220px;
background: mediumblue;
color: white;
height: 200vh;
}
#media (min-width: 1050px){
.main{
margin: 0 220px 0 220px;
}
}
<div class="wrapper">
<div class="sidebar">
Sidebar
</div>
<div class="main">
Main
</div>
</div>
» JSBin

Make div stick to top of page after scrolling past another div?

<div id="header"></div>
<div id="sticky"></div>
<div id="section"></div>
<div id="footer"></div>
<style>
body { margin: 0px; background-color: #e3e3e3; }
#header { background-color: #cb5454; height: 140px; }
#sticky { background-color: #546bcb; height: 70px; }
#section { height: 1500px; }
#footer { background-color: #cb5454; height: 140px; }
</style>
Here is my code: http://jsfiddle.net/uaqh018d/
I want #sticky to stick to the top of the page after scrolling past #header. I also want it hidden until stuck. And then of course have it unstick+hide again after scrolling back up to #header.
How can I achieve this?
I would recommend adding a class to #sticky when it's ready to be fixed to the top of the screen, and then removing that class when you want to 'unstick' it. Then you can manipulate that class in CSS.
e.g. for a class fixed you'd put the following in your CSS:
#sticky {
display: none;
background-color: #546bcb;
height: 70px;
}
#sticky.fixed {
display: block;
position: fixed;
top: 0;
width: 100%;
}
And then your jQuery would look like this:
$(window).scroll(function() {
var distanceFromTop = $(this).scrollTop();
if (distanceFromTop >= $('#header').height()) {
$('#sticky').addClass('fixed');
} else {
$('#sticky').removeClass('fixed');
}
});
Here's an updated FIDDLE
I might also recommend some jQuery fade or slide effects (see the fiddle).
You can use position: fixed and in js detect when user scroll like this:
$(document).scroll(function() {
//detect when user scroll to top and set position to relative else sets position to fixed
$("#sticky").css({
"top": "0",
"position": $(this).scrollTop() > 140 ? "fixed" : "relative"
});
});
body {
margin: 0px;
background-color: #e3e3e3;
}
#header {
background-color: #cb5454;
height: 140px;
}
#sticky {
background-color: #546bcb;
height: 70px;
width: 100%;
position: fixed;
}
#section {
height: 1500px;
}
#footer {
background-color: #cb5454;
height: 140px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="header"></div>
<div id="sticky"></div>
<div id="section"></div>
<div id="footer"></div>
References
.scroll()
In my case, the div I wanted to be sticky was inside of another div (ie. not stuck to the page, but in another fixed div on the side of the page). Here's my adaptation of #bowhart's answer to solving this problem given a React component (sticky_adapter.js):
module.exports.makeItSticky = function(thisReactComponent, parentScrollNode = window) {
const thisNode = $(ReactDOM.findDOMNode(thisReactComponent));
const position = thisNode.position();
// Uncomment for verbose logging
//console.log("Initial position: " + UIUtils.stringify(position));
const scrollContainer = $(parentScrollNode);
scrollContainer.scroll(() => {
const distanceFromTop = scrollContainer.scrollTop();
// Uncomment for verbose logging
//console.log("ScrollTop: " + distanceFromTop);
if (distanceFromTop > position.top) {
thisNode.addClass("stick-to-top");
} else {
thisNode.removeClass("stick-to-top");
}
});
};
Now, to make any React component sticky, I just add to the class:
componentDidMount() {
StickyAdapter.makeItSticky(this, ".some-other-div-which-is-the-container");
}
Finally, the css for the sticky class:
.stick-to-top {
display: block;
position: sticky;
top: 0;
z-index: 10;
}
Hey this is and old question but for new visitors I think u just need to add this css code to #sticky:
#sticky { position:sticky;top:0; }
and no need for javascript.
sticky toggles between relative and fixed, depending on the scroll position.
and don't forget that, the parent also should not have overflow property

Categories

Resources