This one is maybe a big riddle. Maybe its not. I want to change the color of a position:fixed
menu when scrolling.
EDIT: proven that it does NOT work on Firefox, so probably this is just a Chrome quirk, still interesting behaviour so I'll leave this answer if anyone just wants to build a Chrome only implementation or when Firefox and other browsers come along.
There, I "fixed" it (pun intended :) )
Look at this working fiddle: JSFiddle example of fixed, relative and overflow working together
You can use relative
parents with overflow
to mimic the effect of the changing color.
Downside: you have to duplicate your menu (which is semantically well, just plain wrong). You could use some basic javascript to do the duplication of the menu though, that would improve it a little. I also only tested this on Chrome, but it seems really basic CSS so I imagine this will work on any browser / device.
Code snippets (the relevant parts)
HTML
<div class="topbar">
<h1>Whoo pink!</h1>
<div class="fixed-menu">Fixed!</div>
</div>
<div class="loads-of-content">
<div class="fixed-menu">Fixed!</div>
</div>
CSS
.topbar {
position: relative;
overflow: hidden;
z-index: 3;
}
.topbar .fixed-menu {
color: red;
}
.fixed-menu {
position: fixed;
top: 20px;
right: 50px;
}
.loads-of-content {
position: relative;
overflow: hidden;
}
If you don't want to have to manage duplicate elements to pull off this effect with CSS clip
as per Antony's solution, then you can use a couple jQuery plugins:
jq-clipthru - This is a superflexible plugin that can probably do everything you want (and a lot more), but it also requires the jQuery UI library. [Demo]
Unobscure Text - This is my very lightweight plugin that has a very specific use case, but it's not compatible with jQuery 3. [Demo]
If you require jQuery 3 support and don't care for IE 11 and below, then you can use a solution based on SVG clip-path
, like this.
What you are looking for is clipping. This allows you to specify a rectangular region where an element is visible.
You can use:
clip: rect(auto, auto, auto, auto);
on the container to emulate overflow: hidden
for the position: fixed
menu, so you can crop the text as you scroll.
Note that while clip
is deprecated, the new clip-path
does not work with position: fixed
elements, so you are stuck with clip
for now.
clip
requires absolute or fixed positioning, but you can easily work around that problem by placing a position: absolute
element inside a position: relative
container, like so:
<div style="position: relative;">
<div style="position: absolute; clip: rect(auto, auto, auto, auto);">
<!-- My awesome menu here -->
</div>
</div>
Here is the demo:
html,
body {
height: 100%;
margin: 0;
padding: 10% 5% 80% 5%;
background-color: #eee;
font-family: sans-serif;
}
.container {
display: table;
width: 100%;
height: 100%;
background-color: #fff;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
position: relative;
}
.cell.small {
height: 25%;
}
.header,
.content,
.footer {
position: absolute;
width: 100%;
height: 100%;
padding: 4%;
box-sizing: border-box;
clip: rect(auto, auto, auto, auto);
}
.header,
.footer {
background-color: #F97D9F;
}
.menu {
position: fixed;
font-size: 2em;
top: 10%;
right: 20%;
}
.white {
color: #fff;
}
.black {}
<div class="container">
<div class="row">
<div class="cell small">
<div class="header">
content
<div class="menu white">MENU</div>
</div>
</div>
</div>
<div class="row">
<div class="cell">
<div class="content">
content
<div class="menu black">MENU</div>
</div>
</div>
</div>
<div class="row">
<div class="cell small">
<div class="footer">
content
<div class="menu white">MENU</div>
</div>
</div>
</div>
</div>
The behaviour you are looking for is the same as background-attachement:fixed;
.
Although this solution is pretty simple and doesn't rely on JS, from a sematic point of view it shouldn't be recommended.
The point is to use 2 background images with background-attachement: fixed;
and to position the link over them for interaction. It will give you the desired behaviour with a smooth color change according to the background color :
DEMO
header, article,footer,body{
background:#fff url('http://i.imgur.com/oHIZBHL.png') no-repeat;
background-attachment: fixed;
background-position:right 160px top 10px;
}
body{
padding:0 150px 1000px;
background-color:lightgrey;
}
header,footer{
background-image:url('http://i.imgur.com/79IWeQK.png');
background-color:#F97D9F;
height:125px;
}
article{
height:500px;
}
nav a{
position:fixed;
top:10px; right:160px;
width:150px; height:50px;
}
<nav><a href="#" title="menu"></a></nav>
<header></header>
<article></article>
<footer></footer>