CSS animation: control which element respects the screen size limits

Asked

Viewed 916 times

2

I made a basic animation of a div that oscillates between the left and right side of the screen indefinitely. It occurs that when reaching the right edge of the screen, the div exceeds the visible field causing part of it to disappear. I would like the div respect the screen size and never exceed 100%. I cannot use 95% in left, because the percentage will vary according to the resolution of the user. I need it to be accurate for any resolution.

Follow the fiddle: https://jsfiddle.net/3xt9zc6c/

@-webkit-keyframes anima{
    0%{
        top: 0px;
        left: 0px;
    }   
    50%{
        top: 0px;
        left: 100%;
    }
    100%{
        top: 0px;
        left: 0px;
    }
}
#circle{
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: red;
    position: relative;
    top: 0px;
    left: 0px;
    -webkit-animation: anima 8s infinite;
}
<body>
    <div id="circle"></div>
</body>

2 answers

4


The initial solution was to put a container to limit the action of the object:

@keyframes anima{
    0%{ left: 0; }	
   50%{ left: 100%;}
  100%{ left: 0; }
}

#container {
  width:100%;
  box-sizing:border-box;
  position:relative;
  padding-right:40px;
  border:1px solid green;
}

#circle{
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: red;
  position: relative;
  top: 0;
  left: 0;
  animation: anima 8s infinite;
}
<body>
  <div id="container">
	<div id="circle"></div>
  </div>  
</body>

I took advantage and adjusted the CSS. When you set a value zero, you should not specify units.

The explanation is as follows: the way you did the animation, what is being animated is the upper left corner of the object, so 100% means that the left margin will be at the edge of the screen (consequently the object will be out).

Putting a padding on the right side, the same width of the object, we are compensating for the size of this.

The green edge is just so you can view the animation working properly. The margins that remain around the container are of body, I didn’t take it in the example CSS, but just add a rule to remove it.

To conclude, the box-sizing:border-box; makes our container 100% wide consider 100% including the padding we insert in the measure (and up to the green edge).


Evolving the idea

After a conversation in the comments, in which the author asked about the possibility of having a solution where it is not necessary to know beforehand the size of the padding, I reached a cleaner conclusion, which does not depend on container, and fits the size of the object:

@keyframes anima{
  0%{ left:0;transform:translateX(0); }	
  50%{ left:100%;transform:translateX(-100%); }
  100%{ left:0;transform:translateX(0); }
}

#ball1, #ball2 {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: red;
  position: relative;
  left:0;
  transform:translateX(0);
  animation: anima 5s infinite ease-in-out;
}

#ball2 {
  width:100px;
  height:100px;
  background-color:blue;
}

body, html {
  margin:0;
  padding:0;
}
<body>
  <div id="ball1"></div>  
  <div id="ball2"></div>  
</body>

The trick here was to move the animation pivot, which goes from the top left to the top right, using translate(), so that when arriving at the right margin the object does not leave the screen.

I took the opportunity to change the measurements to simulate the full screen without edge, with the element actually touching the margins.

  • ok got it. Now answer me one thing, which I was initially thinking about and didn’t put in the question. And if the size of the red ball were dynamic, that is, if the width and height were variable (controlled by javascript or on the server), is there any solution where I don’t need to define the padding-right:40px? That would be interesting because it would have a more generic solution.

  • This demand is quite different from the original question proposal. I will give a thought here. Although if you are going to control by JS or the server, just change the properties in both places, no? (both the object and the container)

  • the size of the ball would be programmatically changed via JS. Then you would have to programmatically change the padding-right as well... I think it works. But it would be more "clean" if there was some way to make it pure CSS.

  • I thought about using the css’s Calc() function, but I don’t know if it would be possible in that context

  • @Maigret I think I’ve solved.

  • 1

    show! now it’s top.

Show 1 more comment

1

Just add a margin-left: -40px, since the #circle has a width: 40px.

Running here: https://jsfiddle.net/3xt9zc6c/1/

@keyframes anima{
    0%{
        top: 0px;
        left: 0px;
    }   
    50%{
        top: 0px;
        left: 100%;
        margin-left: -40px;
    }
    100%{
        top: 0px;
        left: 0px;
    }
}
#circle{
width: 40px;
height: 40px;
border-radius: 50%;
background-color: red;
position: relative;
top: 0px;
left: 0px;
-webkit-animation: anima 8s infinite;
-moz-animation: anima 8s infinite;
animation: anima 8s infinite;
        transition: all 0.4s ease-in-out;
}
    <div id="circle"></div>

  • Animate has stopped working, it does not animate continuously.

  • In my case it works, if you’re using Google Chrome, try adding another animation, this time without the -webkit-.

  • but it’s not the same result anymore. The animation becomes binary, the circle starts on the left and then jumps to the right, without making the transition gradually.

  • I edited the answer with a possible solution.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.