Change appearance of sticky element when it reaches sticky position - css

I have create a bottom div that is present all the time when scrolling the site. Its "natural" stop is right after the footer. When I do scroll, and it's not at the footer, it is a bit transparent. However, what I would like to do is when the sticky div reaches the bottom (i.e. its "true" position), then the background changes or something like that.
Is that possible WITHOUT using JS or something like that ?
Updated with a fiddle:
https://jsfiddle.net/octvg6mn/
HTML:
<div class="largeDiv"></div>
<div class="stickyDiv">Test</div>
CSS:
.largeDiv {
height: 1500px;
width: 100%;
background: #cccccc;
}
.stickyDiv {
position: sticky;
bottom: 0px;
text-align: center;
background: blue;
color: white;
opacity: 0.8;
padding: 25px;
}
.stickyDiv:hover {
opacity: 1.0;
}
So as you can see in the fiddle, the sticky has a light opacity while scrolling, but when I reach the bottom, where it is supposed to be, I would like it to turn the opacity into 1.0 or something like, just like when hovering the mouse.

You can apply an opaque background to the container to simulate this. When the sticky element will reach the bottom that background will hide the transparency:
.largeDiv {
height: 1500px;
width: 100%;
background: #cccccc;
}
.container {
background:rgba(0,0,255,1);
}
.stickyDiv {
position: sticky;
bottom: 0px;
text-align: center;
background:rgba(0,0,255,0.5);
color: white;
padding: 25px;
}
.stickyDiv:hover {
background:rgba(0,0,255,1);
}
<div class="container">
<div class="largeDiv"></div>
<div class="stickyDiv">Test</div>
</div>

Related

Use a dynamically expanding div as clipping mask for background image in parent

I'm looking for a CSS solution that adapts to div contents, with the functionality of clip-path but dynamic. This is my code:
.background {
background: yellow;
text-align: center;
}
.text {
display: inline-block;
margin: 20px;
padding: 20px;
background: teal;
}
<div class="background">
<div class="text">
My text is in here
</div>
</div>
Yellow and teal are just used for illustration. I want to replace the yellow background with an image, but only show it in the teal area. The div.background spans the width of the browser, but I cannot make assumptions about the width of div.text. Can this be done with only CSS or does it require JS and dynamically setting background-position?
Use a pseudo element that you make relative to the background element
.background {
background: yellow;
text-align: center;
position: relative;
z-index: 0;
}
.text {
display: inline-block;
color: #fff;
margin: 20px;
padding: 20px;
clip-path: inset(0); /* clip to only text element */
}
.text:before {
content: "";
position: absolute;
z-index: -1;
inset: 0;
background: url(https://picsum.photos/id/1056/800/600) center/cover;
}
/* to illustrate */
.text:hover {
clip-path: none;
}
<div class="background">
<div class="text">
My text is in here
</div>
</div>
Here is one way of doing what you want through JS. The image is in the background element, and it is clipped according to the dimensions of the child element. There's a resize observer applied to the child element to trigger the calculation of the clipping mask whenever the dimensions of the child change.
I've added an animation to show how the clipping is calculated in real-time, but as you can see there is some slight stutter.
let text = document.querySelector('.text');
let bg = document.querySelector('.background');
let observer = new ResizeObserver(() => {
calculateClipPath(bg, text);
})
observer.observe(text);
function calculateClipPath (parent, child) {
parent.style.clipPath = `inset(
${child.offsetTop}px
${parent.clientWidth - (child.offsetLeft + child.clientWidth)}px
${parent.clientHeight - (child.offsetTop + child.clientHeight)}px
${child.offsetLeft}px
)`;
}
.background {
background: url(https://c4.wallpaperflare.com/wallpaper/368/148/1024/flowers-roses-drawing-light-wallpaper-preview.jpg);
text-align: center;
position: relative;
}
.text {
display: inline-block;
margin: 20px;
padding: 40px;
width: 200px;
animation: 3s infinite change;
}
#keyframes change {
0% {
width: 200px;
}
50% {
width: 150px;
}
100% {
width: 200px;
}
}
<div class="background">
<div class="text">
My text is in here
</div>
</div>
I'm still experimenting to see if there is a purely CSS version of the solution because that would always be smoother than the JS solution. If I can figure it out, I'll edit this answer and add it here

CSS: Background color on text doesn't work when the line breaks in responsive mode [duplicate]

This question already has answers here:
Thick underline behind text
(7 answers)
Closed 8 months ago.
I am trying to use a background color on text only, which works fine on single lines, but when the line breaks in responsive mode it ends up looking like this:
Does anyone know what to add to make the yellow background line follow the text on mulitple lines?
This is my code:
.background-highlight {
position: relative;
display: inline-block;
color: #faf9f4;
}
.background-highlight:after {
content: '';
position: absolute;
width: 100%;
height: 10px;
left: 0;
top: 50%;
background-color: #cef230;
z-index: -1;
}
Thanks a lot in advance,
I have used box-decoration-break: clone; property for mainting the same design for multiple lines don't forget to add display: inline; to its child where background is added. in child I have used linear gradient you can generate according to you from here. you can chenge the position of green strip by adjusting gradient values from the site.
.background-highlight {
position: relative;
display: inline-block;
color: #000;
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
font-size: 120px;
}
.background-highlight span {
display: inline;
background: rgb(206,242,48);
background: -webkit-gradient(linear, left bottom, left top, color-stop(11%, rgba(206,242,48,1)), color-stop(12%, rgba(255,255,255,0)));
background: -o-linear-gradient(bottom, rgba(206,242,48,1) 11%, rgba(255,255,255,0) 12%);
background: linear-gradient(0deg, rgba(206,242,48,1) 11%, rgba(255,255,255,0) 12%);
}
<h1 class="background-highlight"><span>The skippers escape</span></h1>
It is fault of pseudo element that is forced to break between two lines.
The cause is the way the effect is carried out, pseudo element ::before creates a single rectangle that has no way of splitting up to follow words flow. Posible solutions:
Make sure links never occupy more than 1 line. You can use
white-space: nowrap;
Redesign the effect applying box border to main element. For example:
.background-highlight {
width: max-content;
border-bottom:5px solid rgb(217, 255, 0);
}
<div class="background-highlight">THE SKIPPERĀ“S ESCAPE</div>
Pseudo-element solution
Use the bottom-positioning value on the pseudo-element instead of top. This forces the pseudo-element to be positioned at the bottom, instead of 50%from the top. I used bottom: -10px as that is the height of the pseudo-element, so it aligns perfectly.
Read more on position values: https://developer.mozilla.org/en-US/docs/Web/CSS/position
HTML-element solution
Instead of creating a pseudo-element, you could opt to make an HTML element instead.
Make a parent container, apply flex to it so the text and the line will align.
Make the .line-element a block element, so it will break into a new line.
You can still apply position: absolute and position: relative on the .line and the h2 if you want to position it in another way. Or you could simply use e.g. transform: translateY(5px) to move the line up a bit.
.background-highlight {
position: relative;
display: inline-block;
color: black;
text-align: right;
}
.background-highlight:after {
content: '';
position: absolute;
width: 100%;
height: 10px;
left: 0;
bottom: -10px;
background-color: #cef230;
z-index: -1;
}
/* Without pseudo */
.nopseudo {
display: flex;
}
.nopseudo h2 {
text-align: right;
}
.nopseudo .line {
height: 10px;
width: 100%;
background-color: #cef230;
display: block;
}
<h2 class="background-highlight">The Skippers <br>Escape</h2>
<div class="nopseudo">
<h2>The Skippers <br>Escape<span class="line"></span></h2>
</div>
I don't know how is your structure but this might help.
We just need two div elements, one as a container to setup the width property and the text holder in this case I will use a h2 tag.
Just mkae the ::after pseudo element as display and the .background-highlight's width can be width: match-content or 100% in this case if you just want to cover the text use match-content if you want to cover the width of the .title element use 100%
.title {
width: 90vw;
text-align: end;
}
h2 {
text-transform: uppercase;
color: #374650;
}
.fullwidth {
width: 100%;
}
.match {
width: match-content;
}
.background-highlight {
position: relative;
display: inline-block;
}
.background-highlight:after {
content: '';
display: block;
width: 100%;
height: 10px;
background-color: #cef230;
z-index: -1;
}
<div class="title">
<h2 class="match background-highlight">
The Skipper's <br>Escape</h2>
</div>
<div class="title">
<h2 class="fullwidth background-highlight">
The Skipper's <br>Escape</h2>
</div>

Modal isn't covering the whole document

I am currently trying to make my .modal class's black background span the whole document length and width (not just the whole viewport, which it is currently doing). It would also be great to make it so you couldn't scroll the document anymore until you interacted with it.
I have verified that its parent container would be body, which I believe should be at least 600px due to my containers having a minimum height of 300px each and them being stacked on top of each other. I have used both 100% width and 100% height and absolutely positioned my element but have had no luck with it covering anything past the bottom of the viewport. I used z-index to ensure it was sitting on top of the other elements in the page and nothing seems to work.
<body>
<main class="todo">
<section class="todo__ctn todo__ctn--lists">
<span>Hello man...lists</span>
</section>
<section class="todo__ctn todo__ctn--tasks">
<span>Hello man...tasks</span>
</section>
</main>
<div class="modal">
<div class="modal__content">
<p>Hello Man...content</p>
</div>
</div>
</body>
````````````````
/* SCSS Styling */
* {
box-sizing: border-box;
}
.todo {
display: grid;
grid-template-columns: repeat(auto-fit,minmax(300px,1fr));
border: 1px solid black;
&__ctn {
min-height: 300px;
&:first-child {
border-bottom: 1px solid black;
}
}
&__ctn--lists {
background: gold;
}
&__ctn--tasks {
background: tan;
}
}
.modal {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
background: rgba(0,0,0,.8);
color: orange;
&__content {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
}
}
Like I had mentioned, I would like to have the black background persist, even when you scroll down the page. Once I scroll past the bottom of the viewport, the black background seems to stop and I don't know why.

prevent jumping of affixed element when scrolled

I'm using bootstrap's affix plugin here
HTML:
<html>
<head>
...
<style>
h1 {
width: 100px;
height: 100px;
background: green;
margin: 0;
top: 10px;
}
h1.affix {
top: 8px;
}
body {
padding: 10px;
height: 5000px;
}
</style>
</head>
<body>
<h1 data-spy="affix" data-offset-top="10">yo!</h1>
</body>
</html>
Whenever I scroll down for a considerable distance (using scroll on the right, not the mouse scroll), the div jumps. How can I prevent that? Apperantly the problem is div scrolls up beyond the screen, then it's applied a fixed position and it moves down causing it to jump. I tried using transition to make it jump smoother, but for some reason it didn't work.
h1 {
width: 100px;
height: 100px;
background: green;
margin: 0;
transition-property: top;
transition-duration: 3s;
}
How can I fix this?
Try this:
Use affix class
<h1 class="affix">yo!</h1>
Now it will not jump !

fixed size centered div surrounded by expanding divs

I am working on a website and the client wants to have something similar to this: http://www.csszengarden.com/?cssfile=202/202.css
There are several overlays that are attached to the edges of the screen, while the text in the center is contained in such a way that the original browser scroll bars remain usable. This design is made elastic by allowing it to stretch at least vertically through an extra div.
The tricky part about my design: I have a fixed size div that is supposed to be centered both vertically and horizontally. What I need now are further divs that surround the centered div and expand as the user resizes their window, in order to serve as overlays to hide the text below them.
This is basically it: http://imgur.com/TNaTU
So broken down even further, what I need is a way to have the four surrounding divs automatically expand or reduce their size so they always fill up all of the screen.
Is there a way to do this without Javascript?
This won't work in IE7 without some crazy hacks, because IE7 does not support display: table and friends.
I will have a look at making this work in IE7 if it's a requirement for you.
Tested in IE8 and recent versions of Firefox, Chrome, Safari, Opera.
Live Demo (edit)
HTML:
<div id="top">top stretch</div>
<div id="middle">
<div id="middleContainer">
<div class="stretch">left stretch</div>
<div id="fixed">fixed</div>
<div class="stretch">right stretch</div>
</div>
</div>
<div id="bottom"><div id="bottomContent">bottom stretch</div></div>
CSS:
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden
}
#top, #bottom {
position: absolute;
left: 0;
right: 0;
text-align: center
}
#top {
top: 0;
height: 50%
}
#bottom {
bottom: 0;
height: 50%
}
#bottomContent { /* you don't need this if bottom won't hold "content" */
position: absolute;
right: 0; bottom: 0; left: 0
}
#fixed {
width: 400px
}
#middle {
background: #ee1c24;
position: absolute;
width: 100%;
height: 300px;
top: 50%;
margin-top: -150px; /* height/2 */
left: 0;
z-index: 1
}
#middleContainer {
display: table;
width: 100%;
height: 100%
}
.stretch, #fixed {
display: table-cell
}
/* just for demo */
#top, #bottom, .stretch {
background: #b5e61d;
border: 5px solid #000
}
#fixed {
border-top: 5px solid #000;
border-bottom: 5px solid #000
}

Resources