1

I am experimenting with pseudo elements and i am wondering why the .container::after element is changing its position during the animation. Here is the HTML and the CSS code:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  height: 100vh;
}

header {
  position: sticky;
  top: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0.3rem;
  background-color: steelblue;
  z-index: 1;
}

main {
  display: flex;
  flex-flow: column nowrap;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  background-color: grey;
  height: 100%;
  position: relative;
}

div {
  border: 10px solid red;
  background-color: white;
}

main:hover .container {
  transform: rotate(360deg);
  color: purple;
  transition: all 2s;
}

main .container::after {
  position: absolute;
  top: 200px;
  left: 100px;
  background-color: white;
  color: gold;
  content: "after div";
}
<header>
  <h1>stuff</h1>
</header>
<main>
  <div class="container">I am a container</div>
</main>

I tried to put the

position: relative 

on the div element. But this is not what i want. Obviously the ::after element gets related to its parent element (div) during the animation but why is that? Can i avoid that?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Hiwa
  • 11
  • 2
  • Well, I don't really know, but I suggest reading here: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations – Ramzi Khahil Mar 14 '23 at 11:26
  • I didnt find the problem on this, but thank you :) – Hiwa Mar 14 '23 at 11:42
  • 1
    _"wondering why the .container::after element is changing its position during the animation"_ - uhm, it _isn't_ ...? It is part of the div's content, and as such is of course _also_ affected by your rotate transformation. Remember, ::before and ::after render, as if they were _child elements_ inserted in first/last position - if you had put a `span` into the container instead of pseudo elements, it would behave exactly the same. – CBroe Mar 14 '23 at 12:14
  • add `transform: rotate(0deg);` to `.container` without hover. This will help make it the same and then set your position accordingly – Shariq Shahid Mar 14 '23 at 12:18
  • @CBroe look at the ::after element on the website. It is above the .container element on the left side (because i wanted it there). As soon as you hover over the main section the animation begins (as wanted) and somehow the ::after element is changing its position. It has nothing to do with the animation itself. You can put transform: rotate(0) in as the animation and the position of after is still changing. – Hiwa Mar 14 '23 at 12:49
  • Ah, that you had it somewhere else before the animation starts, was hard to see in the little snippet window. Yes, applying _any_ kind of `transform`, creates a new positioning context. So the moment this applies, the reference point for the absolute positioning is not the `main` element with its `position: relative` any more, but the div container becomes the positioning context. – CBroe Mar 14 '23 at 13:29
  • Yeah such a weird behaviour. Avoiding this seems not that easy. – Hiwa Mar 14 '23 at 13:52

1 Answers1

0

I'm not quite sure what is it that you're trying to achieve. But you can create a group element that includes two elements. One the ::before element which now is a normal div and the second your .container element.

And then if you give the animation to the .container element only, the ::before element will not move. Because its not inside the other one.

Here's the code:

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Document</title>
</head>
<body>
<header>
    <h1>stuff</h1>
</header>
<main>
    <div class="container">I am a container</div>
    <div class="previousAfter">after div</div> <!-- I added this line -->
</main>
</body>
</html>

CSS:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    height: 100vh;
}

header {
    position: sticky;
    top: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 0.3rem;
    background-color: steelblue;
    z-index: 1;
}

main {
    display: flex;
    flex-flow: column nowrap;
    justify-content: center;
    align-items: center;
    font-size: 2rem;
    background-color: grey;
    height: 100%;
    position: relative;
}

div {
    border: 10px solid red;
    background-color: white;
}

main:hover .container {
    transform: rotate(360deg);
    color: purple;
    transition: all 2s;
}

main .previousAfter { /* I changed this line */
    position: absolute;
    top: 200px;
    left: 100px;
    background-color: white;
    color: gold;
}

Let me know if this is what you were looking for.

Arshaan
  • 61
  • 6
  • Hey Arshaan. This is not exactly what i wanted. I want a pseudo element (::after or ::before) which i can manipulate. My problem is that the ::after element is changing its position during a a animation on the parent element. I understand that ::after "inherit" the animation. But why the after element, which i put on the top left side on the website somehow gets rendered under the .container element when the animation is active? The animation itself doesnt matter. Put transform: rotate(0); instead and you will see the position changing has nothing to do with the rotation. – Hiwa Mar 14 '23 at 12:56
  • @Hiwa Oh! I just realized what you meant. I researched a bit and it's a bug on browsers end. Although there are several solutions you can try [here](https://stackoverflow.com/questions/15194313/transform3d-not-working-with-position-fixed-children). Let me know if you couldn't find anything useful. – Arshaan Mar 14 '23 at 13:18
  • Yeah, it seems really to be a bug... This definetly helped me, thank you! – Hiwa Mar 14 '23 at 13:26
  • No, it's _not_ a bug - as the accepted answer in that thread already explains, https://stackoverflow.com/a/15256339/1427878 – CBroe Mar 14 '23 at 13:30