CSS - ::after pseudo element positioning and dimension issue - css

I have 2 images with transparent background and need to put one on top of each other with the same positioning:
1 spinning (underneath)
1 fixed (above)
I need to have the whole image composition to be centered and to have its size adjusted depending on the window size.
I used an ::after pseudo element for the fixed one but couldn’t get its position and size to follow the spinning one.
I suppose the background-size property should be involved but didn’t manage to use it properly.
Would appreciate any advice, even if it involves going with a totally different approach than the ::after pseudo class.
Many thanks.
body{
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container{
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container{
}
.engine-complete{
position: relative;
width: 100%;
height: auto;
margin: 0 auto;
}
.engine-complete::after{
content: "";
position: absolute;
width: 191px;
height: 192px;
top: 1px;
left: 0;
background-image: url(https://image.ibb.co/jOqNma/engine1_crpd.png);
}
.engine-rotating{
width: 50%;
height: auto;
}
.spin {
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function:linear;
animation-play-state: running;
}
#keyframes spin {
from {
transform:rotate(360deg);
}
to {
transform:rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<div class="engine-complete">
<img src="https://image.ibb.co/nwOKXF/engine1.png" width=191 height=192 class="engine-rotating spin"/>
</div>
</div>
</div>

Something like this?
EDIT: Instead of setting the image as a background using the ::after pseudo-class, I added the fixed image into the html. I also eliminated one of your containers.
I centred the animated image using text-align:center and centred the fixed image using position: absolute
I set both images to 30% width relative their parent .engine-container
The fixed image has a higher z-index than the animated image so that it always appears over it. The images also change size accordingly, relative to window size.
body {
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container {
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container {
text-align: center;
position: relative;
}
.engine-rotating,
.engine-fixed {
width: 30%;
}
.engine-fixed {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(0deg);
z-index: 5000;
}
.spin {
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
}
#keyframes spin {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<img src="https://image.ibb.co/nwOKXF/engine1.png" class="engine-rotating spin" />
<img src="https://image.ibb.co/jOqNma/engine1_crpd.png" class="engine-fixed" alt="">
</div>
</div>
UPDATE
Heres what I came up with:
A similar effect using ::after. I was able to achieve this by inserting the image url into the content: rule, rather than setting a background image.
body {
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container {
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container{
text-align: center;
position: relative;
}
.engine-rotating{
}
.engine-container::after{
content: url('https://image.ibb.co/jOqNma/engine1_crpd.png');
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(0deg);
z-index: 5000;
}
.spin{
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
}
#keyframes spin{
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<img src="https://image.ibb.co/nwOKXF/engine1.png" class="engine-rotating spin" />
</div>
</div>

Set position for .engine-complete::after to relative
.engine-complete::after {position: relative}
body{
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container{
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container{
}
.engine-complete{
position: relative;
width: 100%;
height: auto;
margin: 0 auto;
}
.engine-complete::after{
content: "";
position: relative; /* this was changed */
width: 191px;
height: 192px;
top: 1px;
left: 0;
background-image: url(https://image.ibb.co/jOqNma/engine1_crpd.png);
}
.engine-rotating{
width: 50%;
height: auto;
}
.spin {
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function:linear;
animation-play-state: running;
}
#keyframes spin {
from {
transform:rotate(360deg);
}
to {
transform:rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<div class="engine-complete">
<img src="https://image.ibb.co/nwOKXF/engine1.png" width=191 height=192 class="engine-rotating spin"/>
</div>
</div>
</div>

Related

CSS Animation changing height is jittering

I'm trying to make an animation for drawing a square border on hover.
It's working fine but when drawing the left side of the border the bottom of the border is jittering
Here's a link to the codepen https://codepen.io/Taggagii/pen/GRxYpXY to see the code and the jittering that's happening.
My approach is to just animate the ::before element to render the top and right sides and the ::after element to render the bottom and left sides. To animate both of them I'm just modifying their width and height attributes so it doesn't really make sense to me that only the bottom is jittery and not all the sides.
Note: This issue is present on Chrome but not on Firefox
html {
background: #f58442;
}
.center {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.border-renderer {
--border-size: 1px;
--animation-duration: 4s;
--border-z-index: -1;
--border-color: black;
--second-border-final-extent: calc(100% + 2 * var(--border-size));
--first-border-final-extent: calc(100% + var(--border-size));
--size: 200px;
position: relative;
display: inline-block;
background: #ccba87;
padding: 10px;
font-size: 5em;
margin-left: 35vw;
margin-top: 40vh;
}
.border-renderer::before,
.border-renderer::after {
content: '';
background: var(--border-color);
position: absolute;
z-index: var(--border-z-index);
}
.border-renderer::before {
top: calc(-1 * var(--border-size));
left: 0;
}
.border-renderer::after {
top: var(--first-border-final-extent);
right: calc(-1 * var(--border-size));
transform: translateY(-100%);
}
.border-renderer:hover::before {
animation-name: draw-box-top-right;
animation-duration: calc(var(--animation-duration) / 2);
animation-timing-function: ease;
animation-fill-mode: forwards;
}
.border-renderer:hover::after {
animation-name: draw-box-bottom-left;
animation-duration: calc(var(--animation-duration) / 2);
animation-delay: calc(var(--animation-duration) / 2);
animation-timing-function: ease;
animation-fill-mode: forwards;
}
#keyframes draw-box-top-right {
0% {
width: 0%;
height: var(--border-size);
}
50% {
width: var(--first-border-final-extent);
height: var(--border-size);
}
100% {
width: var(--first-border-final-extent);
height: var(--first-border-final-extent);
}
}
#keyframes draw-box-bottom-left {
0% {
width: var(--border-size);
height: var(--border-size);
}
50% {
width: var(--second-border-final-extent);
height: var(--border-size);
}
100% {
width: var(--second-border-final-extent);
height: var(--second-border-final-extent);
}
}
<div class="holder">
<div class="border-renderer">
<div class="center">Mouse over me</div>
</div>
</div>

CSS Keyframe I cannot seem to remove an artifact

I have a simple scaling animation applied to a circle using keyframes.
There is an unexpected and undesirable line that scales with the circle in Chrome Version 85.0.4183.102 (Official Build) (64-bit) and not in Firefox or Safari.
I cannot remove it - do you know how to? I have tried adding border: 0 to the various divs unsuccessfully.
#parent { overflow: hidden; background: #F0F4FF; height: 500px; width: 100%; position: relative; user-select: none; margin-block-end: 5rem; z-index: 3; }
.child { width: 100%; height: 100%; }
.child .inner { background: radial-gradient(circle at center, #D90368 20%, #F0F4FF 20%); }
.inner { position: relative; left: 0; top: 0; animation: circle 2s linear infinite; display: block; height:100%; width: 100%; content: " "; }
#keyframes circle { 0% { transform: scale(0.5) } 50% { transform: scale(1.2) } 80% { transform: scale(0.95) } 100% { transform: scale(1.0) } }
<div id='parent'>
<div class='child'>
<span class='inner'></span>
</div>
</div>
I have tried to search SO however I find a lot of similar line / scale / keyframe posts but these are intentional line animation posts.
I had the line to on Chrome. So I edited the code a bit, and the line was gone. Not sure what the problem was, just a different solution:
The html:
<div id="parent">
<div class="child">
<div class="inner"></div>
</div>
</div>
And the CSS
#parent {
overflow: hidden;
background: #f0f4ff;
height: 500px;
width: 100%;
position: relative;
user-select: none;
margin-block-end: 5rem;
z-index: 3;
}
.child {
width: 100%;
height: 100%;
position: relative;
}
.inner {
background-color: #d90368;
width: 10rem;
height: 10rem;
position: absolute;
left: calc(50% - 5rem);
top: calc(50% - 5rem);
animation: circle 2s linear infinite;
display: block;
content: " ";
border-radius: 50%;
}
#keyframes circle {
0% {
transform: scale(0.5);
}
50% {
transform: scale(1.2);
}
80% {
transform: scale(0.95);
}
100% {
transform: scale(1);
}
}

How keep the image rotated during the reverse movement?

I'm having a trouble with the effect I want to create. My body in the HTML file it's just a div with two images.
I was trying to give animation to the first image in the following way:
in 0% it starts at the beginning of the div (the fish's head is on the right)
in 100% it ends in the end, but at this point I want to rotate the image and keep that effect until it gets 0% again. (that is, the fish should point towards the left during the reverse motion)
But it just rotates in 100% and no more. I don't know if this happens because I don't understand some concept of the animation property.
This is all my code:
#keyframes fish01 {
0% {
left: 0%;
transform: rotateY(180deg);
}
1% {
transform: rotateY(0deg);
}
99% {
transform: rotateY(0deg);
}
100% {
left: 90%;
transform: rotateY(180deg);
}
}
body {
background-color: black;
}
div {
position: absolute;
margin-left: 18%;
margin-top: 3%;
width: 800px;
height: 500px;
border: 5px double #DDDDDD;
border-radius: 1em 1em;
background-image: url("https://i.onthe.io/vllkyt28101smv87bg.349283fe.jpg");
}
div img:nth-child(1) {
float: left;
position: absolute;
margin: 0px;
top: 20%;
width: 100px;
height: 50px;
transform: scale(1.5, 1.5);
animation-name: fish01;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in;
}
div img:nth-child(2) {
float: left;
position: absolute;
top: 20%;
left: 60%;
}
<section>
<div>
<img src="https://www.hyperone.com.eg/media/catalog/product/cache/4/thumbnail/9df78eab33525d08d6e5fb8d27136e95/f/i/fish_1.png" />
<img src="http://www.pets4homes.co.uk/images/fish_hero.png" />
</div>
</section>
I've tried everything in the #keyframes and looked into W3Schools website about animation property, but it didn't help me. Any suggestions?
Reason:
The behavior that is seen is expected one based on your #keyframes and the animation-direction setting. When the animation's direction is set to alternate, the UA executes the animation from 0 to 100 for the odd numbered iterations, 100 to 0 for the even numbered iterations.
As per your keyframes, the transform goes from rotateY(180deg) to rotateY(0deg) at 1% of the animation's duration itself and so during the odd numbered iterations you don't see any visible rotation (as duration is pretty small) and it goes from rotateY(180deg) (at 100%) to rotateY(0deg) (at 99%) because of which you don't get to see any visible rotation during even numbered iterations also.
The problem in writing keyframes for forward direction and re-using the same for the reverse (using animation-direction) is that it can be done only when the states are the same for both. In this case, it is not because the element should be in unrotated state during forward movement and should have rotateY(180deg) during the reverse movement.
Solution:
For the element to be seen in its rotated state, the transform must be retained for some time. So, for your case it is better to do away with the animation-direction: alternate setting and write both the forward and reverse motions within the keyframes itself like in the below snippet.
(Note: Since we are writing both forward and reverse motions within the keyframes, you may have to double the animation-duration).
#keyframes fish01 {
0% {
left: 0%;
transform: rotateY(0deg);
}
49.5% {
left: 90%;
transform: rotateY(0deg);
}
50.5% {
left: 90%;
transform: rotateY(180deg);
}
100% {
left: 0%;
transform: rotateY(180deg);
}
}
body {
background-color: black;
}
div {
position: absolute;
margin-left: 18%;
margin-top: 3%;
width: 800px;
height: 500px;
border: 5px double #DDDDDD;
border-radius: 1em 1em;
background-image: url("https://i.onthe.io/vllkyt28101smv87bg.349283fe.jpg");
}
div img:nth-child(1) {
float: left;
position: absolute;
margin: 0px;
top: 20%;
width: 100px;
height: 50px;
transform: scale(1.5, 1.5);
animation-name: fish01;
animation-duration: 10s; /* double of original time */
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: ease-in;
}
div img:nth-child(2) {
float: left;
position: absolute;
top: 20%;
left: 60%;
}
<section>
<div>
<img src="https://www.hyperone.com.eg/media/catalog/product/cache/4/thumbnail/9df78eab33525d08d6e5fb8d27136e95/f/i/fish_1.png" />
<img src="http://www.pets4homes.co.uk/images/fish_hero.png" />
</div>
</section>
The problem was that you had animation-direction: alternate; in your CSS. To compensate for removing this, you also need to make the img moving to left: 90% being at the 50% mark in the animation, not the 100% mark.
Hope this helps! :)
#keyframes fish01{
0% {
left: 0%;
transform: rotateY(0deg);
}
49% {
transform: rotateY(0deg);
}
50% {
left: 90%;
transform: rotateY(180deg);
}
99% {
transform: rotateY(180deg);
}
100% {
left: 0%;
transform: rotateY(0deg);
}
}
body {
background-color: black;
}
div {
position: absolute;
margin-left: 18%;
margin-top: 3%;
width: 800px;
height: 500px;
border: 5px double #DDDDDD;
border-radius: 1em 1em;
background-image: url("https://i.onthe.io/vllkyt28101smv87bg.349283fe.jpg");
}
div img:nth-child(1) {
float: left;
position: absolute;
margin: 0px;
top: 20%;
width: 100px;
height: 50px;
transform: scale(1.5, 1.5);
animation-name: fish01;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: ease-in;
}
div img:nth-child(2) {
float: left;
position: absolute;
top: 20%;
left: 60%;
}
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8"/>
<title>CSS rotate animation</title>
<link rel="stylesheet" href="Transicion02.css"/>
</head>
<body>
<section>
<div>
<img src="https://www.hyperone.com.eg/media/catalog/product/cache/4/thumbnail/9df78eab33525d08d6e5fb8d27136e95/f/i/fish_1.png"/>
<img src="http://www.pets4homes.co.uk/images/fish_hero.png"/>
</div>
</section>
</body>
</html>

Animate CSS background-position with smooth results (sub-pixel animation)

I'm trying to animate the background-position of a div, slowly, but without it having jerky movement. You can see the result of my current efforts here:
http://jsfiddle.net/5pVr4/2/
#-webkit-keyframes MOVE-BG {
from {
background-position: 0% 0%
}
to {
background-position: 187% 0%
}
}
#content {
width: 100%;
height: 300px;
background: url(http://www.gstatic.com/webp/gallery/1.jpg) 0% 0% repeat;
text-align: center;
font-size: 26px;
color: #000;
-webkit-animation-name: MOVE-BG;
-webkit-animation-duration: 100s;
-webkit-animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
}
I have been at this for hours and can't find anything that will animate slowly and smoothly at a sub-pixel level. My current example was made from the example code on this page: http://css-tricks.com/parallax-background-css3/
The smoothness of animation I'm after can be seen on this page's translate() example:
http://css-tricks.com/tale-of-animation-performance/
If it can't be done with the background-position, is there a way to fake the repeating background with multiple divs and move those divs using translate?
Checkout this example:
#content {
height: 300px;
text-align: center;
font-size: 26px;
color: #000;
position:relative;
}
.bg{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: -1;
background: url(http://www.gstatic.com/webp/gallery/1.jpg) 0% 0% repeat;
animation-name: MOVE-BG;
animation-duration: 100s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
#keyframes MOVE-BG {
from {
transform: translateX(0);
}
to {
transform: translateX(-187%);
}
}
<div id="content">Foreground content
<div class="bg"></div>
</div>
http://jsfiddle.net/5pVr4/4/
Animating background-position will cause some performance issues. Browsers will animate transform properties much cheaply, including translate.
Here is an example using translate for an infinite slide animation (without prefixes):
http://jsfiddle.net/brunomuller/5pVr4/504/
#-webkit-keyframes bg-slide {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
.wrapper {
position:relative;
width:400px;
height: 300px;
overflow:hidden;
}
.content {
position: relative;
text-align: center;
font-size: 26px;
color: #000;
}
.bg {
width: 200%;
background: url(http://www.gstatic.com/webp/gallery/1.jpg) repeat-x;
position:absolute;
top: 0;
bottom: 0;
left: 0;
animation: bg-slide 20s linear infinite;
}
You should adjust your HTML and CSS little bit
Working Demo
HTML
<div id="wrapper">
<div id="page">
Foreground content
</div>
<div id="content"> </div>
</div>
CSS
#-webkit-keyframes MOVE-BG {
from { left: 0; }
to { left: -2000px; }
}
#wrapper {
position:relative;
width:800px;
height: 300px;
overflow:hidden;
}
#page {
text-align: center;
font-size: 26px;
color: #000;
}
#content {
width: 2000px;
height: 300px;
background: url(http://www.gstatic.com/webp/gallery/1.jpg) 0% 0% repeat;
position:absolute;
top: 0;
left: 0;
z-index:-1;
-webkit-animation-name: MOVE-BG;
-webkit-animation-duration: 100s;
-webkit-animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
}

Firefox: Multiple borders with border-radius set, overlayed on top of each other, show ragged edges

The HTML
<div id='loader'>
<div id='loaderLargeSlice' class='loaderSlice'>
<div class='arc'></div>
<div class='arc'></div>
<div class='arc'></div>
</div>
</div>
The CSS
#loader{
position: relative;
width: 100px;
height: 100px;
margin: 14px;
border-radius: 50%;
background: none;
}
.loaderSlice
{
position:absolute;
display:block;
opacity: 0.5;
}
#loaderLargeSlice
{
height: 100px;
width: 100px;
animation: spin 4s linear 0s infinite forwards;
-webkit-animation: spin 4s linear 0s infinite forwards;
}
.arc
{
position: absolute;
top: -14px;
left: -14px;
width: 100%;
height: 100%;
background: none;
border: 14px solid rgba(0,0,0,0);
border-top-color: black;
border-radius: 50%;
}
.arc + .arc
{
transform: rotate(70deg);
-webkit-transform: rotate(70deg);
}
.arc + .arc + .arc
{
transform: rotate(140deg);
-webkit-transform: rotate(140deg);
}
The Problem
Firefox shows ragged edges
Anyone know of a fix?
Answering as unfixable. See #Eevee's comment on the main post.

Resources