For a web application meant for mobile browsers, I want to integrate this simple yet elegant preloader. It's going to reside on top of a translucent overlay. It's also going to have some words on top of it (e.g. "Please wait...", or "Hold on a minute..." etc).
I tried integrating all that. The result is below (run the snippet). It has 3 distinct problems (can you help me solve them all):
1) I haven't been able to position the preloader + it's text on top of the translucent overlay (although I've used a high z-index).
2) Moreover, the preloader graphic is getting skewed in accordance with the length of the sentence on top of it. I want it to be independent of that.
3) Lastly, they're not positioned in the exact middle (vertically speaking).
body{background:#ECF0F1}
.parent{
position:fixed;
z-index:1;
top:50%;
left:50%;
transform:translate(-50%, -50%);
}
.caption{
margin-bottom:1em;
color:gray;
position:relative;
z-index:10;
}
.load{
width:50px;
height:50px;
position:relative;
z-index:10;
}
.load hr{border:0;margin:0;width:40%;height:40%;position:fixed;border-radius:50%;animation:spin 2s ease infinite}
.load :first-child{background:#19A68C;animation-delay:-1.5s}
.load :nth-child(2){background:#F63D3A;animation-delay:-1s}
.load :nth-child(3){background:#FDA543;animation-delay:-0.5s}
.load :last-child{background:#193B48}
#keyframes spin{
0%,100%{transform:translate(0)}
25%{transform:translate(160%)}
50%{transform:translate(160%, 160%)}
75%{transform:translate(0, 160%)}
}
.overlay{
position:fixed;
width:100%;
height:100%;
top:0;
left:0;
opacity:0.6;
z-index:100;
background-color:#FFFFFF;
}
body {
background: #E8F5E9;
background: repeating-linear-gradient(
to right,
#FAFAFA,
#FAFAFA 50px,
#E8F5E9 50px,
#E8F5E9 100px
);
}
<body>
<div class="overlay">
<div class="parent">
<div class="caption">Lorem ipsum dolor sit amet ...</div>
<div class="load">
<hr><hr><hr><hr>
</div>
</div>
</div>
<body>
Note: I'm hoping for pure CSS solutions, no JS involvement. I'd also want to avoid flex-box, and go for something universal (in a backward compatibility sense). E.g. flex-box support dwindles in older versions of Android browser (according to caniuse.com). I want to respect those versions too, hence it's best to stick to well-supported CSS 2.1 properties.
The issue is with the hr element they are placed fixed and they should be absolute to keep their relation with parent container. And then simply add margin:auto to load to center them.
And since parent and overlay elements are both fixed position you can separate them to be able to correctly use z-index and avoid the opacity being applied of overlay:
body {
background: #ECF0F1
}
.parent {
position: fixed;
z-index: 1000;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.caption {
margin-bottom: 1em;
color: gray;
position: relative;
z-index: 10;
}
.load {
width: 50px;
height: 50px;
position: relative;
z-index: 10;
margin: auto;
}
.load hr {
border: 0;
margin: 0;
width: 40%;
height: 40%;
position: absolute;
border-radius: 50%;
animation: spin 2s ease infinite
}
.load :first-child {
background: #19A68C;
animation-delay: -1.5s
}
.load :nth-child(2) {
background: #F63D3A;
animation-delay: -1s
}
.load :nth-child(3) {
background: #FDA543;
animation-delay: -0.5s
}
.load :last-child {
background: #193B48
}
#keyframes spin {
0%,
100% {
transform: translate(0)
}
25% {
transform: translate(160%)
}
50% {
transform: translate(160%, 160%)
}
75% {
transform: translate(0, 160%)
}
}
.overlay {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
opacity: 0.6;
z-index: 100;
background-color: #FFFFFF;
}
body {
background: #E8F5E9;
background: repeating-linear-gradient( to right, #FAFAFA, #FAFAFA 50px, #E8F5E9 50px, #E8F5E9 100px);
}
<div class="overlay">
</div>
<div class="parent">
<div class="caption">Lorem ipsum dolor sit amet ...</div>
<div class="load">
<hr>
<hr>
<hr>
<hr>
</div>
</div>
The preloader is a child of the overlay, therefore it will have the parent opacity, no way to avoid that but setting it outside the overlay, maybe as a sibling, and adjust the overlay with a negative z-index
As for the sizing, the he are ignoring the parent size as they are set to position:fixed, should be absolute
body {
background: #ECF0F1
}
.parent {
position: fixed;
z-index: 1;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.caption {
margin-bottom: 1em;
color: gray;
position: relative;
z-index: 10;
}
.load {
width: 50px;
height: 50px;
position: relative;
z-index: 10;
margin: auto;
}
.load hr {
border: 0;
margin: 0;
width: 40%;
height: 40%;
position: absolute;
border-radius: 50%;
animation: spin 2s ease infinite
}
.load :first-child {
background: #19A68C;
animation-delay: -1.5s
}
.load :nth-child(2) {
background: #F63D3A;
animation-delay: -1s
}
.load :nth-child(3) {
background: #FDA543;
animation-delay: -0.5s
}
.load :last-child {
background: #193B48
}
#keyframes spin {
0%,
100% {
transform: translate(0)
}
25% {
transform: translate(160%)
}
50% {
transform: translate(160%, 160%)
}
75% {
transform: translate(0, 160%)
}
}
.overlay {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
opacity: 0.6;
z-index: -10;
background-color: #FFFFFF;
}
body {
background: #E8F5E9;
background: repeating-linear-gradient( to right, #FAFAFA, #FAFAFA 50px, #E8F5E9 50px, #E8F5E9 100px);
}
<div class="overlay">
</div>
<div class="parent">
<div class="caption">Lorem ipsum dolor sit amet ...</div>
<div class="load">
<hr>
<hr>
<hr>
<hr>
</div>
</div>
Related
I am working a project on my favorite science stories animated using HTML. While I was working on it By just changing the position to fixed or nothing position of all my objects was changing. If you remove the position property from #Guy, you will notice that the image of Galileo will shift drastically. I just want to know why this happens.
:root {
--initX: 280px;
--initY: 70px;
--finalY: 600px;
}
body {
background-color: aqua;
padding: 0px;
margin: 0px;
}
#Guy {
z-index: 4;
height: 200px;
position: fixed;
width: auto;
transform: translate(800px, 450px);
}
#Galilo {
height: 50px;
width: auto;
z-index: -1;
transform: translate(290px, 5px) rotateZ(4deg);
}
#tower {
height: 650px;
width: 150px;
z-index: 0;
transform: translate(250px, 50px) rotateZ(4deg);
position: absolute;
background-color: grey;
}
#Lball {
height: 40px;
width: 40px;
z-index: 2;
border-radius: 50%;
transform: translate(var( --initX), var(--initY));
background-color: blue;
position: absolute;
animation: lite 2s linear 1s infinite forwards;
}
#Hball {
height: 50px;
width: 50px;
z-index: 3;
transform: translate(calc(var( --initX) + 75px), var(--initY));
border-radius: 50%;
background-color: red;
position: absolute;
animation: heavy 2s linear 1s infinite forwards;
}
#floor {
height: 25%;
width: 100%;
background-color: green;
position: absolute;
z-index: -1;
transform: translate(0px, 565px);
}
#hide {
height: 12%;
width: 100%;
background-color: green;
position: absolute;
z-index: 1;
transform: translate(0px, 650px);
}
#keyframes lite {
0% {
transform: translate(var( --initX), var(--initY))
}
90% {
transform: translate(var(--initX), calc(var(--finalY) + 12.5px))
}
100% {
transform: translate(var(--initX), calc(var(--finalY) + 12.5px))
}
}
#keyframes heavy {
0% {
transform: translate(calc(var( --initX) + 75px), var(--initY))
}
90% {
transform: translate(calc(var( --initX) + 75px), var(--finalY))
}
100% {
transform: translate(calc(var( --initX) + 75px), var(--finalY))
}
}
<div id="tower"></div>
<div id="Hball"></div>
<div id="Lball"></div>
<div id="floor"></div>
<div id="hide"></div>
<img src="stick fidure.png" alt="Dude thinking" id="Guy">
<img src="galileo-galilei.png" alt="gallilo" id="Galilo">
P.S.
The link for the image of Galileo is https://cdn.images.express.co.uk/img/dynamic/109/590x/galileo-galilei-819977.jpg and the stick figure was made in Paint 3D
position: fixed takes the element out of the document flow and places it in relation to the viewport/window. Usually that also causes this element to overlap other elements. The other elements however will be rearranged in a way like the fixed element wouldn't be there (it's not in the document flow). So adding/removing position: fixed to/from an element will have all these effects on the overall document.
I'm trying to make a 'dot' orbit around another object (circle) but due to the z-index the dot always appears above the circle it is meant orbiting around.
CodePen link: https://codepen.io/moy/pen/ROVZXd?editors=1100
Ideally the 2nd half of the animation would take place behind the object so it's not seen until it comes out the other side - is that possible?
I thought about fading out the object that is moving around but I don't think that would give a smooth/masked effect?
A bit stuck as to how I'd mask this area as I can't see a way the CSS would know it's meant to be hidden. I thought maybe I could change the z-index 50% though the animation it and reset it at 0%/100% but that doesn't appear to do anything.
Any ideas? Thanks in advance!
.earth {
background: white;
border: 1px solid black;
border-radius: 50%;
display: block;
height: 100px;
margin: 30px auto;
position: relative;
width: 100px;
z-index: 20;
}
.orbit {
border: 2px #eee transparent;
border-radius: 50%;
height: 140px;
margin: auto;
position: absolute;
top: -20px;
left: -20px;
transform: rotateZ(60deg) rotateY(60deg);
transform-style: preserve-3d;
width: 140px;
z-index: 10;
}
.orbit .moon {
animation: move ease-in-out infinite;
animation-duration: 2s;
background: black;
border-radius: 50%;
height: 15px;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 15px;
z-index: 10;
}
#keyframes move {
0% {
transform: rotateZ(-90deg) translateX(70px) rotateZ(90deg) rotateY(-70deg); z-index: 20;
}
50% {
z-index: -20;
}
100% {
transform: rotateZ(270deg) translateX(70px) rotateZ(-270deg) rotateY(-70deg); z-index: 20;
}
}
<div class="earth">
<div class="orbit">
<div class="moon"></div>
</div>
</div>
I seem to have solved this by adding a negative z-index to an animation applied to the parent .orbit
Link: https://codepen.io/moy/pen/wZdpRw?editors=1100
I initially applied this at 50% through the animation as that should be the furthest away the dot is before it comes back behind the larger circle. However this didn't work, setting it on 100% did work. Not entirely sure why but it seems to work!
The initial issue was due to the fact that you are applying z-index to the parent element and doing so it will impossible to make the child to move behind it (Why elements with any z-index value can never cover its child?) thus changin z-index is useless
Even if you remove the z-index from the parent you still have the transform that is also creating a stacking context making impossible to the child element to move behind so you cannot make the .moon to move behind the .earth.
The only way to do it (like you already noticed) is to remove z-index from the .earth to avoid the earth creating a stacking context and animate z-index of orbit to make the orbit AND the moon moving behind the earth (not only the moon).
Add some coloration to better see this:
.earth {
background: white;
border: 1px solid black;
border-radius: 50%;
display: block;
height: 100px;
margin: 60px auto;
position: relative;
width: 100px;
}
.orbit {
animation: hide ease-in-out infinite;
animation-duration: 2s;
background:red;
border-radius: 50%;
height: 140px;
margin: auto;
position: absolute;
top: -20px;
left: -20px;
transform: rotateZ(60deg) rotateY(60deg);
transform-style: preserve-3d;
width: 140px;
}
.orbit .moon {
animation: move ease-in-out infinite;
animation-duration: 2s;
background: black;
border-radius: 50%;
height: 15px;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 15px;
}
#keyframes move {
0% {
transform: rotateZ(-90deg) translateX(70px) rotateZ(90deg) rotateY(-70deg);
}
100% {
transform: rotateZ(270deg) translateX(70px) rotateZ(-270deg) rotateY(-70deg);
}
}
#keyframes hide {
0% {
z-index: 20;
}
100% {
z-index: -20;
}
}
<div class="earth">
<div class="orbit">
<div class="moon"></div>
</div>
</div>
Now if you add back z-index to earth it will stop working because of the stacking context:
.earth {
background: white;
border: 1px solid black;
border-radius: 50%;
display: block;
height: 100px;
margin: 60px auto;
position: relative;
width: 100px;
z-index:2;
}
.orbit {
animation: hide ease-in-out infinite;
animation-duration: 2s;
background:red;
border-radius: 50%;
height: 140px;
margin: auto;
position: absolute;
top: -20px;
left: -20px;
transform: rotateZ(60deg) rotateY(60deg);
transform-style: preserve-3d;
width: 140px;
}
.orbit .moon {
animation: move ease-in-out infinite;
animation-duration: 2s;
background: black;
border-radius: 50%;
height: 15px;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 15px;
}
#keyframes move {
0% {
transform: rotateZ(-90deg) translateX(70px) rotateZ(90deg) rotateY(-70deg);
}
100% {
transform: rotateZ(270deg) translateX(70px) rotateZ(-270deg) rotateY(-70deg);
}
}
#keyframes hide {
0% {
z-index: 20;
}
100% {
z-index: -20;
}
}
<div class="earth">
<div class="orbit">
<div class="moon"></div>
</div>
</div>
You can try key-framing the opacity:
.earth {
background: white;
border: 1px solid black;
border-radius: 50%;
display: block;
height: 100px;
margin: 30px auto;
position: relative;
width: 100px;
z-index: 20;
}
.orbit {
border: 2px #eee transparent;
border-radius: 50%;
height: 140px;
margin: auto;
position: absolute;
top: -20px;
left: -20px;
transform: rotateZ(60deg) rotateY(60deg);
transform-style: preserve-3d;
width: 140px;
z-index: 10;
}
.orbit .moon {
animation: move ease-in-out infinite;
animation-duration: 2s;
background: black;
border-radius: 50%;
height: 15px;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 15px;
z-index: 10;
}
#keyframes move {
0% {
transform: rotateZ(-90deg) translateX(70px) rotateZ(90deg) rotateY(-70deg); opacity: 1;
}
56% {
opacity: 1;
}
58% {
opacity: 0;
}
77% {
opacity: 0;
}
78% {
opacity: 1;
}
100% {
transform: rotateZ(270deg) translateX(70px) rotateZ(-270deg) rotateY(-70deg); opacity: 1;
}
}
<div class="earth">
<div class="orbit">
<div class="moon"></div>
</div>
</div>
If a div is nested inside of another, can the nested div ignore the hover of the parent. Here's an example
.Box {
width: 50px;
height: 50px;
background: red;
}
.Circle {
width: 20px;
height: 20px;
background: blue;
border-radius: 20px;
}
.Box:hover {
animation: expand .5s normal forwards;
}
#keyframes expand {
0% {
transform: scale(1);
}
100% {
transform: scale(1.6);
}
}
<div class="Box">
<div class="Circle"></div>
</div>
In this example would there be a way to make the Box expand but not the Circle
Technically the parent hover event doesn't get applied to the child.
But in your case the child is still effected, because you're scaling the parent. And thus everything inside of the parent is being scaled too.
In order to counter the scaling of the nested div, you can apply a reverse scaling effect when the parent div is hovered.
.Box{
width: 50px;
height: 50px;
background: red;
}
.Circle{
width: 20px;
height: 20px;
background: blue;
border-radius: 20px;
}
.Box:hover{
animation: expand .5s normal forwards;
}
.Box:hover .Circle {
animation: contract .5s normal forwards;
}
#keyframes expand {
0% {
transform: scale(1);
}
100% {
transform: scale(1.6);
}
}
#keyframes contract {
0% {
transform: scale(1);
}
100% {
transform: scale(0.625); /* 1 / 1.6 */
}
}
<div class="Box">
<div class="Circle"></div>
</div>
Because you are scaling the parent, everything inside it will be impacted. An alternative solution is to have a different sibling to the circle and apply the animation on that.
CSS:
.Box {
width: 50px;
height: 50px;
background: red;
}
.Circle {
width: 20px;
height: 20px;
background: blue;
border-radius: 20px;
position: absolute;
top: 10px;
left: 10px;
}
.Container {
position: relative;
}
.Box:hover {
animation: expand .5s normal forwards;
}
#keyframes expand {
0% {
transform: scale(1);
}
100% {
transform: scale(1.6);
}
}
HTML:
<div class="Container">
<div class="Box">
</div>
<div class="Circle"></div>
</div>
Demo: http://jsfiddle.net/lotusgodkk/GCu2D/2157/
Here, the circle is positioned so that it's position is not affected by the box
https://jsfiddle.net/vaf6nv36/1/
Can the balloons image slowly transition over the apple image?
I think that I need more transition parameters, or I should use opacity?
Can someone help me?
HTML:
<div class="img1">
</div>
<div class="img2">
</div>
CSS:
.img1, .img2{
border: 1px solid black;
transition: 1s;
position: absolute;
}
.img1{
left: 25%;
height: 500px;
width: 500px;
z-index: 1;
background-image: url(http://cdn.pcwallart.com/images/balloons-photography-vintage-wallpaper-1.jpg);
}
.img2{
right: 25%;
width: 500px;
height: 500px;
bottom: 0;
z-index: 2;
background-image: url(https://i.pinimg.com/736x/c1/7b/15/c17b150e93c4e9c50d963b076484bee7--apple-wallpaper-iphone-wallpaper.jpg);
}
.img1:hover{
z-index: 999;
}
Although theoretically you can transition z-index, it wouldn't make much sense, i.e. would not result in the crossfade effect which you obviously are looking for: z-index values are integers, which - when you change them in the smallest possible steps (integers, no commas) - results in states either before the other one OR behind the other one - no transitional "half states" in between. If you want to do a kind of continuous crossfade between two elements, you should use a transition on opacity.
In your particular case, since your DIVs are not directly above each other, but only overlap each other, you can solve that by having a second DIV identical to img2 (I called its class .img3), but with z-index: 0 and this CSS rule:
.img1:hover + .img2 {
opacity: 0;
}
This will fade out img2, but still show img3, which however is behind img1, creating the impression of a transition between img1 and img2.
https://jsfiddle.net/2a2epLfv/1/
.img1,
.img2,
.img3 {
border: 1px solid black;
transition: 1s;
position: absolute;
}
.img1 {
left: 20%;
height: 300px;
width: 300px;
z-index: 1;
background-image: url(http://cdn.pcwallart.com/images/balloons-photography-vintage-wallpaper-1.jpg);
}
.img2,
.img3 {
right: 20%;
width: 300px;
height: 300px;
top: 100px;
background-image: url(https://i.pinimg.com/736x/c1/7b/15/c17b150e93c4e9c50d963b076484bee7--apple-wallpaper-iphone-wallpaper.jpg);
}
.img2 {
z-index: 2;
}
.img3 {
z-index: 0;
}
.img1:hover+.img2 {
opacity: 0;
}
<div class="img1"></div>
<div class="img2"></div>
<div class="img3"></div>
I fear z-index transition only makes the element pass step by step through every layer. To make a nice effect you need to combine it with opacity transition and scale / position transition. The fiddle to show you the idea:
.img1, .img2{
border: 1px solid black;
transition: 1s;
position: absolute;
}
.img1{
left: 25%;
height: 500px;
width: 500px;
z-index: 1;
transform: scale(0.9);
opacity: 0.5;
background-image: url(http://cdn.pcwallart.com/images/balloons-photography-vintage-wallpaper-1.jpg);
}
.img2{
right: 25%;
width: 500px;
height: 500px;
bottom: 0;
z-index: 2;
background-image: url(https://i.pinimg.com/736x/c1/7b/15/c17b150e93c4e9c50d963b076484bee7--apple-wallpaper-iphone-wallpaper.jpg);
}
.img1:hover{
animation: fronte 1s linear forwards;
}
#keyframes fronte {
from { z-index: 0; transform: scale(0.9); opacity: 0.5; }
to { z-index: 4; transform: scale(1.1); opacity: 1; }
}
<div class="img1">
</div>
<div class="img2">
</div>
This is the trick I used.
.minus{animation:move 2s;animation-fill-mode:forwards;animation-delay:2s;}
#-webkit-keyframes move {
0 {z-index:1;opacity:1}
50% {opacity:0}
100% { z-index:-1;opacity:1}
}
#keyframes move {
0 {z-index:1;opacity:1}
50% {opacity:0}
100% {z-index:-1;opacity:1}
}
#main{background:red;width:100vw;height:100vh;position:fixed;top:0;left:0;opacity:.9}
.minus{position:fixed;top:10px;left:10px;z-index:1;color:#000}
<div id="main"></div>
<div class="minus">FADE</div>
I want to create an infinitely scrolling (to the left) image animation, where the container is full width and the background image is repeated horizontally. So it will always be like a ticker style - the same image just infinitely moves to the left with no gaps.
Ideally I'd like it to be pure html and css if possible.
This is my attempt - https://jsfiddle.net/7Ljz82n9/
At the moment it moves to the left but there's a gap at the end and it jumps, where am I going wrong?
Html
<div class="tech-slideshow">
<div class="mover-1"></div>
</div>
CSS
.tech-slideshow {
height: 102px;
width:100%;
margin: 0 auto;
position: relative;
overflow: hidden;
transform: translate3d(0, 0, 0);
}
.tech-slideshow > div {
width: 1440px;
background: url(http://placehold.it/1440x102);
position: absolute;
top: 0;
left: 0;
height: 100%;
transform: translate3d(0, 0, 0);
background-repeat:repeat-x;
}
.tech-slideshow .mover-1 {
animation: moveSlideshow 12s linear infinite;
}
#keyframes moveSlideshow {
100% {
transform: translateX(-66.6666%);
}
}
If you are willing to use two divs inside the "slideshow" you could do something like this:
.tech-slideshow {
height: 102px;
width: 100%;
max-width: 1440px; /* Can be at most the width of the image */
margin: 0 auto;
position: relative;
overflow: hidden;
transform: translate3d(0, 0, 0);
}
.wrapper {
height: 102px;
width: 2880px;
}
.wrapper div {
position: absolute;
width: 1440px;
height: 102px;
background: url('http://placehold.it/1440x102') top right no-repeat;
margin: 0;
padding: 0;
animation: movediv 12s linear infinite;
}
.wrapper div.second {
padding-left: 1440px;
animation: movediv 12s linear infinite;
}
#keyframes movediv {
0% { margin-left: 0px; }
100% { margin-left: -1440px; }
}
<div class="tech-slideshow">
<div class="wrapper">
<div class="first"></div>
<div class="second"></div>
</div>
</div>
This will move the divs to the left until a full rotation is made and the second picture is "in the same spot" the first slide and can now be shown again. The padding on the second div is to make it align after the first div. You can alter this to use something else etc.
Here's also a fiddle to play around with: https://jsfiddle.net/thepio/7Ljz82n9/4/
EDIT:
I thought to myself why would this not be possible with using pseudo-elements. And it is! Here's an example of using the pseudo-element ::after with only one div. I think you can figure out the widths, margins and paddings etc (1 x image width or 2 x image width).
.tech-slideshow {
height: 102px;
width: 100%;
max-width: 1440px; /* Can be at most the width of the image */
margin: 0 auto;
position: relative;
overflow: hidden;
transform: translate3d(0, 0, 0);
}
.wrapper {
height: 102px;
width: 2880px;
}
.wrapper div {
position: absolute;
width: 1440px;
height: 102px;
background: url('http://placehold.it/1440x102') top right no-repeat;
margin: 0;
padding: 0;
animation: movediv 12s linear infinite;
}
.wrapper div::after {
display: block;
content: '';
width: 1440px;
height: 102px;
padding-left: 1440px;
background: url('http://placehold.it/1440x102') top right no-repeat;
}
#keyframes movediv {
0% { margin-left: 0px; }
100% { margin-left: -1440px; }
}
<div class="tech-slideshow">
<div class="wrapper">
<div class="first"></div>
</div>
</div>
And also a fiddle about it: https://jsfiddle.net/thepio/05w6ceue/1/