Reputation: 116273
I have a header
element with an article
element below it. The article
has overflow: scroll
. Please see my website here.
My goal is to make the header
semi-transparent so that the article
content will show behind it when scrolled. I want the article
overflow to show with the header
.
The main restriction is that the scrollbar should span from the bottom of the header
, not the top.
How can such an effect be done?
Upvotes: 23
Views: 27515
Reputation: 115
I found small hack around , set header as over-flow:scroll and and put margin value to fill the whole area
(possibly negative value for eg: `margin:0px -6%;`),
so header will be fit to your wish.after that use padding to counter the effect of margin
(for example padding:0px 6%;)
so this will remove the effect of margin we put earlier , so the child container still will be scrollable , where it will be visible for whole area as you wish
Upvotes: 0
Reputation: 116273
A trick is to copy the content. Below is a solution with a blurry and semi-transparent header.
$(function() {
// Clone the content
var $content = $('.content');
var $clone = $('.clone').html($content.html());
// Performance scrolling
var content = $content.get(0);
var clone = $clone.get(0);
content.onscroll = function() {
clone.scrollTop = content.scrollTop;
};
});
div {
width: 400px;
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
}
.content {
top: 50px;
overflow: scroll;
}
.clone {
padding-top: 50px;
overflow: hidden;
-webkit-filter: blur(2px);
}
.header {
height: 50px;
}
.overlay {
background: rgba(240, 240, 240, 0.8);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus at orci vestibulum, congue urna nec, fringilla dolor. Donec pellentesque odio non dui vehicula, eu gravida odio rhoncus. Sed eleifend eu nisi ullamcorper ultricies. Ut ante velit, facilisis
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus at orci vestibulum, congue urna nec, fringilla dolor. Donec pellentesque odio non dui vehicula, eu gravida odio rhoncus. Sed eleifend eu nisi ullamcorper ultricies. Ut ante velit, facilisis
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus at orci vestibulum, congue urna nec, fringilla dolor. Donec pellentesque odio non dui vehicula, eu gravida odio rhoncus. Sed eleifend eu nisi ullamcorper ultricies. Ut ante velit, facilisis
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus at orci vestibulum, congue urna nec, fringilla dolor. Donec pellentesque odio non dui vehicula, eu gravida odio rhoncus. Sed eleifend eu nisi ullamcorper ultricies. Ut ante velit, facilisis
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus at orci vestibulum, congue urna nec, fringilla dolor. Donec pellentesque odio non dui vehicula, eu gravida odio rhoncus. Sed eleifend eu nisi ullamcorper ultricies. Ut ante velit, facilisis
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus at orci vestibulum, congue urna nec, fringilla dolor. Donec pellentesque odio non dui vehicula, eu gravida odio rhoncus. Sed eleifend eu nisi ullamcorper ultricies. Ut ante velit, facilisis
</div>
<div class="header">
<div class="clone"></div>
<div class="overlay"></div>
</div>
Upvotes: 8
Reputation: 2550
Update: Just 'scroll'
events, no 'wheel'
or 'mousewheel'
.
CSS and JavaScript?
Here's a way: (jsfiddle).
Tested in Firefox 46 and Chrome 50.
This solution uses an empty dummy element inside a scrollable element, sized to match the height of the content-bearing element (with hidden scrollbar), and some lightweight JavaScript to relay 'scroll'
events between content and dummy.
scroll
events.<div id="wrapper">
<div id="header"></div>
<!-- An empty dummy to carry the scrollbar -->
<div id="scroll-wrap">
<div id="scroll-dummy"></div>
</div>
<!-- Content -->
<div id="content-view">[Actual content.]</div>
</div>
body { overflow: hidden; }
#content-view {
position: absolute;
z-index: 0;
top: 0; /* Place content behind header. */
height: 100vh; /* Fill viewport. */
overflow-y: scroll; /* Hidden scrollbar. */
}
#header {
position: relative; /* Enable z-index. */
z-index: 1; /* Place header above content. */
height: 25vh; /* Top of viewport. */
}
#scroll-wrap {
position: absolute;
z-index: 1; /* Place scrollbar above content. */
top: 25vh; /* Skip header. */
height: 75vh; /* Fill remaining viewport. */
right: 0; /* Avoid non-scroll mouse events. */
overflow-y: scroll; /* Scrollbar! */
}
#scroll-dummy { width: 1px; } /* Firefox won't scroll width:0 elements! */
var $ = document.getElementById.bind(document),
contentView = $('content-view'), scrollDummy = $('scroll-dummy'),
scrollWrap = $('scroll-wrap'), wrapper = $('wrapper'), header=$('header');
scrollWidth = scrollWrap.offsetWidth - scrollWrap.clientWidth;
// Hide content's actual scrollbar
contentView.style.right = -scrollWidth + 'px';
// Copy height of visible content to hidden dummy
function onContentChange() {
window.requestAnimationFrame(function() {
scrollDummy.style.height = contentView.scrollHeight - header.offsetHeight + 'px';
});
}
window.addEventListener('resize', onContentChange);
onContentChange(); // Call whenever the contentView node changes!
// No event-triggering feedback loops
var fromContent = false, fromScroll = false;
// Update scrollbar scroll on content scroll
animate(contentView, 'scroll', function(e){
if (fromScroll) fromScroll = false;
else {
fromContent = true;
scrollWrap.scrollTop = contentView.scrollTop; // Scroll the scrollbar
}
});
// Update content scroll on scrollbar scroll
animate(scrollWrap, 'scroll', function(){
if (fromContent) fromContent=false;
else {
fromScroll = true;
contentView.scrollTop = scrollWrap.scrollTop; // Scroll the content
}
});
// Wrap event handler with throttled rAF
function animate(element, event, func) {
var lock = false;
element.addEventListener(event, function(e) {
if (!lock) {
lock = true;
window.requestAnimationFrame(function(){ func(e); lock = false; });
}
}, false);
}
Upvotes: 1
Reputation: 3453
Scrollable elements will always clip inner content by their bounding box. Unless they add something like overflow: visible-scroll
to the specs (I wish!).
There's a workaround for this particular case: a custom Webkit scrollbar (Webkit-only, of course). Simply style the "up" button such that its height and background color matches the header's. This will ensure the scroll bar's track does not extend underneath the header, while keeping styling consistent.
JSFiddle: "Webkit Scrollbar Hack For Translucent Headers"
header {
background: rgba(240, 240, 240, 0.9);
height: 60px;
}
::-webkit-scrollbar-button:start {
background: rgba(240, 240, 240, 0.9);
height: 60px;
}
Be sure to pad the top of your scrollable content area.
#content {
padding-top: 60px;
}
As for the non-Webkit browsers, I can think of no CSS-only solutions.
Upvotes: 4
Reputation: 2451
You could do this by adding padding to your content (that scrolls), the same padding as the height of the header. And then moving the content up and under the header (and making the header transparent). Then creating a custom scrollbar with some javascript and html/css that has an offset from the header.
Upvotes: 1