Closed QuincyLarson closed 7 years ago
To animate an element you need to know about the animation properties and the code>@keyframes</code rule. The animation properties control how the animation should behave and code>@keyframes</code rule controls what will happen during that animation. There are 8 animation properties in total, but for now let's go over the two most important ones first:
animation-name
sets the name of the animation
animation-duration
sets the length of the animation
code>@keyframes</code rule on the other hand is really straight forward. You just need to specify what happens to the animated element between 0% and 100% of the duration of the animation. To illustrate the usage of code>@keyframes</code rule and animate properties, let’s look at a simple animated element together.
#anim {
animation-name: colorful;
animation-duration: 3s;
}
@keyframes colorful {
0% {
background-color: blue;
}
100% {
background-color: yellow;
}
}
For the element with the id anim, the code snippet above sets the animation name to colorful and sets the animation duration to 3 seconds. Accordingly for the animation with the name colorful, @keyframes
sets the color to blue at the beginning of the animation (0% ) which will transition to yellow at the end of the animation (100%).
Create an animation for the element with the id rect, set the animation name to rainbow and the animation duration to 4 seconds. Accordingly with the @keyframes
rule, sets the background-color at the beginning of the animation to (0% ) to blue, the middle of the animation (50%) to green and the end of the animation (100%) to yellow.
TO DO
<style>
div{
height:40px;
width: 70%;
background:black;
margin: 50 auto;
border-radius: 5px;
}
/** Only change code below this line. **/
#rect {
}
/** Only change code above this line. **/
</style>
<div id = "rect"></div>
<style>
div{
height:40px;
width: 70%;
background:black;
margin: 50 auto;
border-radius: 5px;
}
#rect {
animation-name: rainbow;
animation-duration: 4s;
}
@keyframes rainbow {
0% {
background-color: blue;
}
50% {
background-color: green;
}
100% {
background-color: yellow;
}
}
</style>
<div id = "rect"></div>
By using a verity of CSS properties such as right
, left
, top
, down
on elements that their position property has been specified (e.g. position = fixed;
) , you could easily create movement.
As shown in the code snippet below, we could achieve a downward movement followed by an upward movement by setting the top
property of the 50% keyframe to 50px and setting the top
property of the the first keyframe (0%) and the last keyframe (100%) to 0px;
@keyframes rainbow {
0% {
background-color: blue;
top: 0px;
}
50% {
background-color: green;
top: 50px;
}
100% {
background-color: yellow;
top: 0px;
}
}
let's see if we can move our element in the horizontal dimension.
Using the left
property, move the element with rect id 0 px to the right at 0% keyframe, 25px at 50% keyframe, and -25px at 100% keyframe.
TO DO
<style>
div{
height:40px;
width: 70%;
background:black;
margin: 50 auto;
border-radius: 5px;
position: relative;
}
#rect {
animation-name: rainbow;
animation-duration: 4s;
}
@keyframes rainbow {
0% {
background-color: blue;
top: 0px;
}
50% {
background-color: green;
top: 50px;
}
100% {
background-color: yellow;
top: 0px;
}
/** Only change code above this line. **/
}
</style>
<div id = "rect"></div>
<style>
div{
height:40px;
width: 70%;
background:black;
margin: 50 auto;
border-radius: 5px;
position: relative;
}
#rect {
animation-name: rainbow;
animation-duration: 4s;
}
@keyframes rainbow {
0% {
background-color: blue;
top: 0px;
left:0px;
}
50% {
background-color: green;
top: 50px;
left:25px;
}
100% {
background-color: yellow;
top: 0px;
left:-25px;
}
}
</style>
<div id = "rect"></div>
Because the following four challenges teach two easy to learn animation properties, I suggest we reduce them to two challenges. we could teach campers about Infinity Property by making a CSS Heartbeat with a Steady Rhythm and teach campers about varying Rhythm by making Stars Twinkle in Different Rates.
Create Rhythm using the Infinity Property Use an the Infinity Property to Make a CSS Heartbeat with a Steady Rhythm
Create a Varying Rhythm Use a Varying Rhythm to Make Stars Twinkle at Different Rates
What do you think? @atjonathan @QuincyLarson
@ahmadabdolsaheb The different animation rates idea is a solid one. That will be really fun! We probably shouldn't call it rhythm, though, since we're using the word rhythm in the context of what @JonathanZWhite proposed for some of the other challenges.
Regarding https://github.com/FreeCodeCamp/CurriculumExpansion/issues/7#issuecomment-241256348 we should choose the most important of these properties and introduce each of them with their own challenge. Showing campers a big list of properties without immediately using them will stress them out. We want to be careful to introduce only one concept per challenge and make sure we immediately apply it so campers will feel confident they understand how it works before moving on.
Other than that little feedback, these challenges are excellent! Keep up the hard work. I am very excited to get this into our codebase and start QA'ing it! :)
@ahmadabdolsaheb you might want to check out DevTips on YouTube (assuming you already haven't). He has recently published a few videos on doing animations using keyframes etc.. in CSS.
Though I think we should be consistent. Instead of using raw CSS, maybe we can use SCSS?
@alayek yes I watched them :+1: thanks tho. We might be better off sticking to raw CSS for consistency.
@QuincyLarson Thanks for your feedback, https://github.com/FreeCodeCamp/CurriculumExpansion/issues/7#issuecomment-241256348 has been updated.
We have 5 challenges in total that require an illustration of Rhythm, all of which require the use of animation properties. (challenge titles are included at the end of the comment)
By looking at the titles, I think they are referring to the definition of Rhythm with a focus on the time dimension similar to Rhythm in film and music. An element can demonstrate Rhythm by it's patterned repetition of movement in space and time such as a beating heart or a twinkling star; however, I think campers could benefit more from a two dimensional demonstration of Rhythm as @JonathanZWhite suggested where it has more UI applications.
If we are going to use Rhythm for other challenges in the curriculum, I suggest reducing the 5 Rhythm challenges to the followings:
Use the Iteration Count Property to Make a CSS Heartbeat Use Different Animation Rates to Make Stars Twinkle
If we are not going to introduce campers to Rhythm anywhere else in the curriculum, I suggest using the followings instead:
Use an the Iteration Count Property to Make a CSS Heartbeat with a Steady Rhythm Use a Varying Rhythm to Make Stars Twinkle at Different Rates
let' me know what you think.
Create Rhythm with CSS animate Property -> Animate Elements using the CSS Animate Property Create Rhythm using the Infinity Property -> Animate Elements Continually using the Infinity Property Use an the Infinity Property to Make a CSS Heartbeat with a Steady Rhythm -> Make a CSS Heartbeat using the Infinity Property Create a Varying Rhythm -> Animate Elements at Variable Rates Use a Varying Rhythm to Make Stars Twinkle at Different Rates -> Animate Multiple Elements at Variable Rates
@alayek I agree with @ahmadabdolsaheb that raw CSS would be better, since we won't introduce SCSS until the "front end frameworks" section much later in the curriculum.
@ahmadabdolsaheb I think we can include all 5 challenges - we just need to change "rhythm" to something else since "rhythm" already has an existing meaning in visual design. I've updated your titles in the issue above.
In the previous challenges we learnt how to use some of the animation properties and the @keyframes rule. Now let's learn about a new property called animation-iteration-count. This property allows you to control how many times you would like to loop through your animation. let's look an example together:
animation-iteration-count: 3;
the above animation will stop after running for 3 times; you could also use infinite
as a value that makes the animation run infinitely.
To keep the ball bouncing on the right for infinity, use the infinite
value in the animation-iteration-count property
, run the animation for the element with the id ball
infinitely;
assert($('#ball').css('animation-iteration-count') == 'infinite', 'message: set the animation-iteration-count to infinite.'),
<style>
#ball{
width: 100px;
height: 100px;
margin: 50 auto;
position: relative;
background: linear-gradient(
35deg,
#ccffff,
#ffcccc
);
}
#ball {
animation-name: bounce;
animation-duration: 1s;
animation-iteration-count: 3;
/** Only change code above this line. **/
}
@keyframes bounce{
0% {
top:0px;
}
50% {
top:249px;
width: 130px;
height: 70px;
}
100% {
top:0px;
}
}
</style>
<div class="img-circle" id= "ball"></div>
<style>
#ball{
width: 100px;
height: 100px;
margin: 50 auto;
position: relative;
background: linear-gradient(
35deg,
#ccffff,
#ffcccc
);
}
#ball {
animation-name: bounce;
animation-duration: 1s;
animation-iteration-count: infinite;
/** Only change code above this line. **/
}
@keyframes bounce{
0% {
top:0px;
}
50% {
top:249px;
width: 130px;
height: 70px;
}
100% {
top:0px;
}
}
</style>
<div class="img-circle" id= "ball"></div>
Since we learnt how to work with the animation-iteration-count
property, let's put our knowledge to work by keeping the heart on the right beating.
On the right screen, we have a heart that is made by a spin element. A div elements is also used to cover the screen completely in the background. Now click on the "Run test" button to run the heartbeat animation.
The one second long heartbeat animation on the right consists of two animated elements. The span
element is animated to change the size using the transform
property. Accordingly the background div is animated to change color using the background
property.
Keep the heart beating by applying the animation-iteration-count
property to the span and the div elements setting its value to infinite
.
assert($('div').css('animation-iteration-count') == 'infinite', 'message: set the animation-iteration-count of the span element to infinite.'),
assert($('span').css('animation-iteration-count') == 'infinite', 'message: set the animation-iteration-count of the div element to infinite.'),
<style>
<style>
div{
position:fixed;
padding:0;
margin:0;
top:0;
left:0;
width: 100%;
height: 100%;
background:white;
animation-name: backdiv;
animation-duration: 1s;
/** Change code above this line. **/
}
span {
margin-top:100px;
width:100%;
font-size:200px;
color:red;
animation-name: beat;
animation-duration: 1s;
text-align: center;
/** Change code above this line. **/
}
@keyframes backdiv{
50% {
background:#ffe6f2;
}
}
@keyframes beat{
0% {
transform: scale(1);
}
50% {
transform: scale(.6);
}
}
</style>
<div></div>
<span id= "heart" class = "glyphicon glyphicon-heart"></span>
<style>
div{
position:fixed;
padding:0;
margin:0;
top:0;
left:0;
width: 100%;
height: 100%;
background:white;
animation-name: backdiv;
animation-duration: 1s;
animation-iteration-count: infinite;
/** Change code above this line. **/
}
span {
margin-top:100px;
width:100%;
font-size:200px;
color:red;
animation-name: beat;
animation-duration: 1s;
text-align: center;
animation-iteration-count: infinite;
/** Change code above this line. **/
}
@keyframes backdiv{
50% {
background:#ffe6f2;
}
}
@keyframes beat{
0% {
transform: scale(1);
}
50% {
transform: scale(.6);
}
}
</style>
<div></div>
<span id= "heart" class = "glyphicon glyphicon-heart"></span>
In the previous challenge, we changed the animation rates for two similarly animated elements by chaining their code>@keyframe</code rule. In this challenge, let's achieve the same goal by altering the animation-iteration-count
of multiple elements.
In the demonstrated animation, there are three stars in the sky that twinkle at the same rate. We need to set the animation-iteration-count
property to dissimilar values for each element so the stars would twinkle at variable rates.
Set the animation-iteration-count
of the elements with the classes star
, star2
, and star3
to 1s, .9s, and 1.1s respectively.
assert($('.star').css('animation-iteration-count') == 'infinite', 'message: set the animation-iteration-count of the element with the class `star` to infinite.'),
assert($('.star2').css('animation-iteration-count') == 'infinite', 'message: set the animation-iteration-count of the element with the class `star2` to infinite.'),
assert($('.star3').css('animation-iteration-count') == 'infinite', 'message: set the animation-iteration-count of the element with the class `star3` to infinite.'),
<style>
#back{
position:fixed;
padding:0;
margin:0;
top:0;
left:0;
width: 100%;
height: 100%;
background:linear-gradient(black,#000099,#66c2ff, #ffcccc);
}
p {
text-align: center;
}
.stars{
font-size:20px;
color:white;
animation-name: twinkle2;
animation-iteration-count: infinite;
}
.star{
margin-top:30px;
left:20%;
animation-duration: 1s;
}
.star2{
left:-20%;
animation-duration: 1s;
}
.star3{
left:10%;
animation-duration: 1s;
}
/** Change code above this line. **/
.rowstars {
position:fixed;
margin: 0 auto;
width:100%;
}
@keyframes twinkle2{
50% {
transform: scale(.1);
opacity: 0.5;
}
}
</style>
<div id="back"></div>
<div id="rowstars">
<p>
<span class = "star stars glyphicon glyphicon-star"></span>
</p>
<p>
<span class = "star2 stars glyphicon glyphicon-star"></span>
</p>
<p>
<span class = "star3 stars glyphicon glyphicon-star"></span>
</p>
</div>
<style>
#back{
position:fixed;
padding:0;
margin:0;
top:0;
left:0;
width: 100%;
height: 100%;
background:linear-gradient(black,#000099,#66c2ff, #ffcccc);
}
p {
text-align: center;
}
.stars{
font-size:20px;
color:white;
animation-name: twinkle2;
animation-iteration-count: infinite;
}
.star{
margin-top:30px;
left:20%;
animation-duration: 1s;
}
.star2{
left:-20%;
animation-duration: .9s;
}
.star3{
left:10%;
animation-duration: 1.1s;
}
/** Change code above this line. **/
.rowstars {
position:fixed;
margin: 0 auto;
width:100%;
}
@keyframes twinkle2{
50% {
transform: scale(.1);
opacity: 0.5;
}
}
</style>
<div id="back"></div>
<div id="rowstars">
<p>
<span class = "star stars glyphicon glyphicon-star"></span>
</p>
<p>
<span class = "star2 stars glyphicon glyphicon-star"></span>
</p>
<p>
<span class = "star3 stars glyphicon glyphicon-star"></span>
</p>
</div>
There are a variety of ways to alter the animation rate of similarly animated elements namely by changing the code>@keyframe</coderule, and the animation-iteration-count
property.
To illustrate, the animation on the right consists of two elements (stars) that each decrease in scale and opacity at 20% of the code>@keyframe</code rule and create the twinkle animation. In this challenge we need to change the code>@keyframe</code rule of the animation of one of the elements so the stars would twinkle at different rates.
Alter the animation rate of the element with the star
class by setting the element's opacity to .5 and and the scale function of its transform property to .5 at 50% of its code>@keyframe</code
TO DO //
<style>
.stars{
color:white;
animation-iteration-count: infinite;
}
.star{
font-size:50px;
margin-top:60px;
left:20%;
animation-duration: 1s;
animation-name: twinkle;
}
.star2{
font-size:30px;
left:-20%;
animation-duration: 1s;
animation-name: twinkle2;
}
@keyframes twinkle{
20% {
transform: scale(.5);
opacity: 0.5;
}
}
/** Change code above this line. **/
@keyframes twinkle2{
20% {
transform: scale(.5);
opacity: 0.5;
}
}
.rowstars {
position:fixed;
margin: 0 auto;
width:100%;
}
#back{
position:fixed;
padding:0;
margin:0;
top:0;
left:0;
width: 100%;
height: 100%;
background:linear-gradient(black,#000099,#66c2ff, #ffcccc, #ffeee6);
}
p{
text-align: center;
}
</style>
<div id="back"></div>
<div id="rowstars">
<p>
<span class = "star stars glyphicon glyphicon-star"></span>
</p>
<p>
<span class = "star2 stars glyphicon glyphicon-star"></span>
</p>
</div>
<style>
.stars{
color:white;
animation-iteration-count: infinite;
}
.star{
font-size:50px;
margin-top:60px;
left:20%;
animation-duration: 1s;
animation-name: twinkle;
}
.star2{
font-size:30px;
left:-20%;
animation-duration: 1s;
animation-name: twinkle2;
}
@keyframes twinkle{
20% {
transform: scale(.5);
opacity: 0.5;
}
}
/** Change code above this line. **/
@keyframes twinkle2{
50% {
transform: scale(.5);
opacity: 0.5;
}
}
.rowstars {
position:fixed;
margin: 0 auto;
width:100%;
}
#back{
position:fixed;
padding:0;
margin:0;
top:0;
left:0;
width: 100%;
height: 100%;
background:linear-gradient(black,#000099,#66c2ff, #ffcccc, #ffeee6);
}
p{
text-align: center;
}
</style>
<div id="back"></div>
<div id="rowstars">
<p>
<span class = "star stars glyphicon glyphicon-star"></span>
</p>
<p>
<span class = "star2 stars glyphicon glyphicon-star"></span>
</p>
</div>
I am working on a few challenges that require the use of animation-timing-function property. I get a "Error: SyntaxError: Unsafe or unfinished function declaration" every time I try to use this property on our website's coding environment. Why is that and how can I fix it?
@ahmadabdolsaheb, use something else like jsfiddle or codepen to test these. This error might be caused by a comment with the word function in it.
@atjonathan I checked it with code pen, it works well. Maybe our coding environment checks for syntax errors and recognizes the animation-timing-function property as an unfinished function declaration. Also, as soon as I change the word function in the property name to something else, I do not get that error.
@ahmadabdolsaheb, don't worry, we can fix these in QA
:shipit:
Ok then I will go ahead and design the challenges in codepen. :dart:
repeating-linear-gradient
is very similar to linear-gradient
with one major difference that is repetition. repeating-linear-gradient
accepts a variety of values but for this challenge we will be working with an angle value and color stop value which is a color value followed by a percentage or a number of pixels.
In the example demonstrated in the code editor on the right, the gradient starts with the color yellow at 0 pixels and it fades into the second color which is blue at 40 pixels away from the start. Then again at 40 pixels the gradient picks the third color and fades it into the forth color value (red ) which is 80 pixels away from the beginning of the gradient. For this example It helps to think about the color stops as pairs where every two colors blend together.
0px [yellow -- blend -- blue] 40px [green -- blend -- red] 80px
So if every two color stop values are similar we end up with stripes that have plane colors because the blend of two similar colors result to the same color.
Let's try to make stripes using the repeating-linear-gradient
by changing the gradient angle to 45 and setting the first two color stops to yellow and the second color stop the black.
assert($('div').css('background') == 'repeating-linear-gradient(45deg, yellow 0px, yellow 40px, black 40px, black 80px);', 'message: set the the first two color stops of the `repeating-linear-gradient` property to yellow and the second color stop the black.'),
<style>
div{
border-radius: 20px;
width: 70%;
height: 400px;
margin: 50 auto;
background: repeating-linear-gradient(
90deg,
yellow 0px,
blue 40px,
green 40px,
red 80px
);
}
/** Only change code above this line. **/
</style>
<div></div>
<style>
div{
border-radius: 20px;
width: 70%;
height: 400px;
margin: 50 auto;
background: repeating-linear-gradient(
45deg,
yellow 0px,
yellow 40px,
black 40px,
black 80px
);
}
/** Only change code above this line. **/
</style>
<div></div>
@ahmadabdolsaheb You've done a wonderful job with these visual design challenges so far, and we're almost done. I was wondering how the remaining challenges are coming along.
Also, we somehow forgot to add challenges about absolute VS relative positioning.
Would you have time in the next few days to create a few quick challenges that teach these?
Newly proposed - create challenges based on position
You could base these off the MDN article: https://developer.mozilla.org/en-US/docs/Web/CSS/position
Thank you @QuincyLarson, I am working on the remaining challenges with the rate of a 1 to 3 challenges per day. I certainly can make some positioning challenges but I am afraid they will not be finished until early September. If you have specific topics in mind, you should go ahead and add them to the list, @atjonathan and I will try to make them as soon as we could.
For this challenge we will be changing the opacity of an animated element so it will fade when it will gradually fade as it reaches the right side of the screen.
In the displayed animation in the right, the round element with the gradient background moves to the right at 50% of its animation's code>@keyframe</code. let's fade the element using the opacity
property at 50% of its animation's code>@keyframe</code so the element fades as it moves to the right.
Fade the element with the id ball
by setting its opacity
property to .1 at 50% of its animation's code>@keyframe</code.
TO DO
<style>
#ball{
width: 70px;
height: 70px;
margin: 50 auto;
position: fixed;
left:20%;
background: linear-gradient(
35deg,
#ccffff,
#ffcccc
);
}
#ball {
animation-name: fade;
animation-duration: 3s;
animation-iteration-count: infinite;
}
@keyframes fade{
50% {
left:60%;
/** Only change code above this line. **/
}
}
</style>
<div class="img-circle" id= "ball"></div>
<style>
#ball{
width: 70px;
height: 70px;
margin: 50 auto;
position: fixed;
left:20%;
background: linear-gradient(
35deg,
#ccffff,
#ffcccc
);
}
#ball {
animation-name: fade;
animation-duration: 3s;
animation-iteration-count: infinite;
}
@keyframes fade{
50% {
left:60%;
opacity:.1;
/** Only change code above this line. **/
}
}
</style>
<div class="img-circle" id= "ball"></div>
To change the scale of an element, css has a handy called tool called transform
property and its scale()
function. For instance, if you would like to increase the size your paragraph elements you should write the following:
p {
transform:scale(2);
}
Now let's change the size of one of the elements displayed in the right;
Increase the size of the element with the id ball2
to 1.5 times of its original size.
TO DO
<style>
.ball{
width: 40px;
height: 40px;
margin: 50 auto;
position: fixed;
background: linear-gradient(
35deg,
#ccffff,
#ffcccc
);
}
#ball{
left:20%;
}
#ball2{
left:65%;
/** Only change code above this line. **/
}
</style>
<div class="img-circle ball" id= "ball"></div>
<div class="img-circle ball" id= "ball2"></div>
<style>
.ball{
width: 40px;
height: 40px;
margin: 50 auto;
position: fixed;
background: linear-gradient(
35deg,
#ccffff,
#ffcccc
);
}
#ball{
left:20%;
}
#ball2{
left:65%;
transform:scale(1.5);
/** Only change code above this line. **/
}
</style>
<div class="img-circle ball" id= "ball"></div>
<div class="img-circle ball" id= "ball2"></div>
Hi folks, positioning challenges in the queue. I changed the order/titles of them a bit, feel free to use them as-is or make edits as you see fit. There are two for relative positioning, one each for fixed and absolute position, and a bonus float one for 5 total.
The adjusted titles are:
CSS treats each HTML element as its own box, which is usually referred to as the "CSS Box Model". Block-level items automatically start on a new line (think headings, paragraphs, and divs) while inline items sit within surrounding content (like images or spans). The default layout of elements in this way is called the "normal flow" of a document, but CSS offers the position
property to override it.
When the position
of an element is set to relative
, it allows you to specify how CSS should move it relative to its current position in the normal flow of the page. It pairs with the CSS offset properties of left
or right
, and top
or bottom
, which say how many pixels, percentages, or ems to move the item away from where it is normally positioned. The following example moves the paragraph 10 pixels away from the bottom:
p {
position: relative;
bottom: 10px;
}
Changing an element's position
to relative
does not remove it from the normal flow - other elements around it still behave as if that item were there.
Change the position
of the h2
to relative
, and use a CSS offset to move it 15 pixels away from the top of where it sits in the normal flow. Notice there is no impact on the positions of the surrounding h1
and p
elements.
<head>
<style>
h2 {
}
</style>
</head>
<body>
<h1>On Being Well-Positioned</h1>
<h2>Move me!</h2>
<p>I still think the h2 is where it normally sits.</p>
</body>
assert($('h2').css('position') === 'relative'), 'message: Add a CSS rule to specify that the <code>h2</code> has a <code>position</code> set to <code>relative</code>.');
assert($('h2').css('top') === '15px'), 'message: Use a CSS offset to relatively position the <code>h2</code> 15px away from the <code>top</code> of where it normally sits.');
<head>
<style>
h2 {
position: relative;
top: 15px;
}
</style>
</head>
<body>
<h1>On Being Well-Positioned</h1>
<h2>Move me!</h2>
<p>I still think the h2 is where it normally sits.</p>
</body>
When combined with an element whose position
is relative
, the CSS offsets of top
or bottom
, and left
or right
tell the browser how far to offset that item relative to where it would sit in the normal flow of the document. This can be slightly confusing, because you're offsetting an element away from given spot, which effectively moves it towards the opposite direction. As you saw in the last challenge, using the top
offset moved the h2
downwards. Likewise, using a left
offset effectively moves an item to the right.
Let's do one more problem for practice. Move the h2
15 pixels to the right and 10 pixels up.
<head>
<style>
h2 {
position: relative;
}
</style>
</head>
<body>
<h1>On Being Well-Positioned</h1>
<h2>Move me!</h2>
<p>I still think the h2 is where it normally sits.</p>
</body>
assert($('h2').css('bottom') === '10px'), 'message: Use a CSS offset to relatively position the <code>h2</code> 10px upwards, in other words, 10px away from the <code>bottom</code> of where it normally sits.');
assert($('h2').css('left') === '15px'), 'message: Use a CSS offset to relatively position the <code>h2</code> 15px towards the right, in other words, 15px away from the <code>left</code> of where it normally sits.');
<head>
<style>
h2 {
position: relative;
bottom: 10px;
left: 15px;
}
</style>
</head>
<body>
<h1>On Being Well-Positioned</h1>
<h2>Move me!</h2>
<p>I still think the h2 is where it normally sits.</p>
</body>
The next option for the CSS position
property is absolute
, which locks the element in place relative to its parent container. Unlike the relative
position, this removes the element from the normal flow of the document, so surrounding items ignore it. The CSS offset properties (top
or bottom
and left
or right
) are used to refine the position.
One nuance with absolute
positioning is that it will be locked relative to its closest positioned ancestor. If you forget to add a position rule to the parent item, (typically position: relative;
), the browser will keep looking up the chain and ultimately default to the body
tag.
Lock the #searchbar
element to the top-right of its section
parent by declaring its position
as absolute
. Give it top
and right
offsets of 0 pixels each.
<style>
#searchbar {
}
section {
position: relative;
}
</style>
<body>
<h1>Welcome!</h1>
<section>
<p>Exciting content</p>
<form id="searchbar">
<label for="search">Search:</label>
<input type="search" id="search" name="search">
<input type="submit" name="submit" value="Go!">
</form>
</section>
</body>
assert($('#searchbar').css('position') === 'absolute'), 'message: Change the <code>position</code> of the <code>#searchbar</code> element to <code>absolute</code>.');
assert($('#searchbar').css('top') === '0px'), 'message: Use the <code>top</code> CSS offset of 0 pixels on the <code>#searchbar</code> element.');
assert($('#searchbar').css('right') === '0px'), 'message: Use the <code>right</code> CSS offset of 0 pixels on the <code>#searchbar</code> element.');
<style>
#searchbar {
position: absolute;
top: 0px;
right: 0px;
}
section {
position: relative;
}
</style>
<body>
<h1>Welcome!</h1>
<section>
<p>Exciting content</p>
<form id="searchbar">
<label for="search">Search:</label>
<input type="search" id="search" name="search">
<input type="submit" name="submit" value="Go!">
</form>
</section>
</body>
The next layout scheme that CSS offers is the fixed
position, which is a type of absolute positioning that locks an element relative to the browser window. Similar to absolute
positioning, it's used with the CSS offset properties and also removes the element from the normal flow of the document. Other items no longer "realize" where it is positioned, which may require some layout adjustments elsewhere.
One key difference from the absolute
position is that the element won't move when the user scrolls.
The navigation bar in the code is labeled with an id
of navbar
. Change its position
to fixed
, and offset it 0 pixels from the top
and 0 pixels from the left
.
<style>
#navbar {
width: 100%;
background-color: #767676;
}
nav ul {
margin: 0px;
padding: 5px 0px 5px 30px;
}
nav li {
display: inline;
margin-right: 20px;
}
a {
text-decoration: none;
}
</style>
<body>
<header>
<h1>Welcome!</h1>
<nav id="navbar">
<ul>
<li><a href="">Home</a></li>
<li><a href="">Contact</a></li>
</ul>
</nav>
</header>
<p>I shift up when the #navbar is fixed to the browser window.</p>
</body>
assert($('#navbar').css('position') === 'fixed'), 'message: Change the <code>position</code> of the <code>#navbar</code> element to <code>fixed</code>.');
assert($('#navbar').css('top') === '0px'), 'message: Use the <code>top</code> CSS offset of 0 pixels on the <code>#navbar</code> element.');
assert($('#navbar').css('left') === '0px'), 'message: Use the <code>left</code> CSS offset of 0 pixels on the <code>#navbar</code> element.');
<style>
#navbar {
position: fixed;
top: 0px;
left: 0px;
width: 100%;
background-color: #767676;
}
nav ul {
margin: 0px;
padding: 5px 0px 5px 30px;
}
nav li {
display: inline;
margin-right: 20px;
}
a {
text-decoration: none;
}
</style>
<body>
<header>
<h1>Welcome!</h1>
<nav id="navbar">
<ul>
<li><a href="">Home</a></li>
<li><a href="">Contact</a></li>
</ul>
</nav>
</header>
<p>I shift up when the #navbar is fixed to the browser window.</p>
</body>
The last positioning tool does not actually use position
, but sets the float
property of an element. Floating elements are removed from the normal flow of a document and pushed to either the left
or right
of their containing parent element. It's commonly used with the width
property to specify how much horizontal space the floated element requires.
Note: Positioning gives you a lot of flexibility and power over the visual layout of a page. It's good to remember that no matter the position of elements, the underlying HTML markup should be organized and still make sense when read from top to bottom. This is how users with visual impairments (who rely on assistive devices like screen readers) access your content.
The given markup would work well as a two-column layout, with the section
and aside
elements next to each other. Give the #left
item a float
of left
and the #right
item a float of right
.
<head>
<style>
#left {
width: 60%;
}
#right {
width: 30%;
}
aside, section {
padding: 5px;
background-color: #ccc;
}
</style>
</head>
<body>
<header>
<h1>Welcome!</h1>
</header>
<section id="left">
<h2>Content</h2>
<p>Prepare to be wowed!</p>
</section>
<aside id="right">
<h2>Sidebar</h2>
<p>Relevant links</p>
</aside>
</body>
assert($('#left').css('float') === 'left'), 'message: Give the <code>#left</code> element a <code>float</code> value of <code>left</code>.');
assert($('#right').css('float') === 'right'), 'message: Give the <code>#right</code> element a <code>float</code> value of <code>right</code>.');
<head>
<style>
#left {
float: left;
width: 60%;
}
#right {
float: right;
width: 30%;
}
aside, section {
padding: 5px;
background-color: #ccc;
}
</style>
</head>
<body>
<header>
<h1>Welcome!</h1>
</header>
<section id="left">
<h2>Content</h2>
<p>Prepare to be wowed!</p>
</section>
<aside id="right">
<h2>Sidebar</h2>
<p>Relevant links</p>
</aside>
</body>
@HKuz, excellent work on these challenges :+1: :tada: :smile: :shipit:
@atjonathan thank you! Since when was there a hamster wearing a fedora emoji? Clearly I've been missing out on life...
@HKuz that's the "shipit squirrel". You can read about him here :shipit:
These challenges are almost done. Thanks for designing these elegant challenges, @HKuz
@ahmadabdolsaheb you have several that are assigned to you. Will you have time to finish these soon? Let us know if we can help 😄
Great job, @HKuz. :squirrel: :raised_hands: @QuincyLarson I will try to get done with a couple today. thanks :blush:
To learn about bezier curves in animations, we need to learn about animation-timing-function
property first that accepts bezier curves as a value. This property controls the change of an animated element during the length of an animation.
In CSS animations, bezier curves are used with the cubic-bezier-curve
function which is a curve that lives on a 1 by 1 coordinate system. The x axis of this coordinate system is the duration of the animation and the y axis is the change in the animation. cubic-bezier-curve
function consists of four main points. p0 and p3 are the beginning and end points which are always located respectively at (0, 0) and (1,1); therefore, to control the shape of the Bezier curve, CSS only allows you to change the x and y values of p1 and p2 two anchor points (x1, y1, x2, y2) . As a result of the shape of the curve, you can control the change of an element in the duration of the animation. Let’s see how cubic bezier curves look in code.
animation-timing-function: cubic-bezier(0.25, 0.25, 0.75, 0.75);
In the example above, the y and x values are equivalent for each point which results in a linear change of an element during the length of an animation.
For the ease of use, predefined keywords could be used instead of popular cubic-bezier-curve
functions. For example, the keyword "linear" is equivalent to a cubic bezier curve that progresses with a constant change of the element during the animation length. Another useful keyword is "ease-out" that describes an animation change that speeds up first and then slows down at the end of the animation. The difference between these two are demonstrated in the screen to the right.
Now, Let’s set a cubic bezier function to its equivalent keyword.
Change the value of the animation-timing-function
property of the element with the id ball
to the keyword equivalent of its current cubic-bezier-curve
function value, linear
.
assert($('#ball').css('animation-timing-function') === 'linear'), 'message: Set the value of the <code>animation-timing-function</code> property of the element with the id <code>ball</code> to <code>linear</code>.');
<style>
.balls{
background: linear-gradient(
35deg,
#ccffff,
#ffcccc
);
position: fixed;
width: 50px;
height: 50px;
margin-top: 50px;
animation-name: bounce;
animation-duration: 2s;
animation-iteration-count: infinite;
}
#ball{
left:27%;
animation-timing-function: cubic-bezier(0.25, 0.25, 0.75, .75);
/** Only change code above this line. **/
}
#ball2{
left:56%;
animation-timing-function: ease-out;
}
@keyframes bounce{
0% {
top:0px;
}
100% {
top:249px;
}
}
</style>
<div class="img-circle balls" id= "ball"></div>
<div class="img-circle balls" id= "ball2"></div>
<style>
.balls{
background: linear-gradient(
35deg,
#ccffff,
#ffcccc
);
position: fixed;
width: 50px;
height: 50px;
margin-top: 50px;
animation-name: bounce;
animation-duration: 2s;
animation-iteration-count: infinite;
}
#ball{
left:27%;
animation-timing-function: linear;
/** Only change code above this line. **/
}
#ball2{
left:56%;
animation-timing-function: ease-out;
}
@keyframes bounce{
0% {
top:0px;
}
100% {
top:249px;
}
}
</style>
<div class="img-circle balls" id= "ball"></div>
<div class="img-circle balls" id= "ball2"></div>
The shipit squirrel, excellent. I hope there isn't a rodent mobster hit out for me after the hamster insult. Well, my world just got a little bit bigger (and a lot brighter) :shipit:
In the previous challenge, we discussed the ease-out
cubic bezier function keyword that describes an animation change that speeds up first and then slows down at the end of the animation. The difference between the ease-out
keyword ( blue element) and linear
keyword (red element) are demonstrated in the right. let's see if we could achieve similar animation progression as the "ease-out" using the cubic bezier curve function.
To see a graphic representation of the bezier curves, lets visit this website.
On the website, by changing the p1 and p2 anchor points you can achieve different bezier curves that controls how the animated change progresses through time.
For our purpose, move the anchor points of the on the graph shown on the website until the configuration is similar to the following:
animation-timing-function: cubic-bezier(0, 0, .58, 1);
In the above cubic-bezier configuration
which is also refereed to as "ease-out", the curve moves faster through the y axis than it moves through the x axis at the beginning. As a result, the change in the animated element progresses faster than the time of the animation. At the end of the curve, the relationship between the x and y values of the curve reverses and the animation progresses slower near end of the animation duration.
To see effect of this bezier curve in action, Let’s adjust the animation-timing-function of the red element to the above-mentioned cubic bezier function configuration so both of the elements progress through the animation with the same rate.
Change value of the animation-timing-function
of the element with the id red
to a cubic-bezier
function with x1, y1, x2, y2 values set respectively to 0, 0, .58, 1.
assert($('#red').css('animation-timing-function') === 'cubic-bezier(0, 0, .58, 1)'), 'message: Set the value of the <code>animation-timing-function</code> property of the element with the id <code>red</code> to a <code>cubic-bezier</code> with x1, y1, x2, y2 values set respectively to 0, 0, .58, 1 .');
assert($('#red').css('animation-timing-function') !== 'linear'), 'message: Change the value of the <code>animation-timing-function</code> property of the element with the id <code>red</code> from <code>linear</code> to another value.');
assert($('#blue').css('animation-timing-function') === 'ease-out'), 'message: Set the value of the <code>animation-timing-function</code> property of the element with the id <code>blue</code> must remain to <code>ease-out</code>.');
<style>
.balls{
position: fixed;
width: 50px;
height: 50px;
margin-top: 50px;
animation-name: bounce;
animation-duration: 2s;
animation-iteration-count: infinite;
}
#red{
background:red;
left:27%;
animation-timing-function: linear;
/** Only change code above this line. **/
}
#blue{
background:blue;
left:56%;
animation-timing-function: ease-out;
}
@keyframes bounce{
0% {
top:0px;
}
100% {
top:249px;
}
}
</style>
<div class="img-circle balls" id= "red"></div>
<div class="img-circle balls" id= "blue"></div>
<style>
.balls{
position: fixed;
width: 50px;
height: 50px;
margin-top: 50px;
animation-name: bounce;
animation-duration: 2s;
animation-iteration-count: infinite;
}
#red{
background:red;
left:27%;
animation-timing-function: cubic-bezier(0, 0, .58, 1);
/** Only change code above this line. **/
}
#blue{
background:blue;
left:56%;
animation-timing-function: ease-out;
}
@keyframes bounce{
0% {
top:0px;
}
100% {
top:249px;
}
}
</style>
<div class="img-circle balls" id= "red"></div>
<div class="img-circle balls" id= "blue"></div>
Challenge Description
We can use CSS keyframes to change the color of a button on hover.
Here's an example of changing the height of an image on hover:
<style>
img:hover {
animation-name: width;
animation-duration: 4s;
}
@keyframes width {
100% {
width: 40px;
}
}
</style>
<img src="https://bit.ly/smallgooglelogo" alt="Google's Logo" />
Change the
background-color
of ourbutton
element on hover to#4791d0
using CSS Keyframes and selecting.btn-primary
.
Challenge Seed
<style>
</style>
<button class="btn btn-primary">Register</button>
Challenge Tests
assert($('.btn-primary:hover').css('background-color:') == '#4791d0', 'message: Your button should have the background-color of <code>#4791d0</code> on hover.')
Challenge Solution
<style>
.btn-primary:hover {
animation-name: background-color;
animation-duration: 4s;
}
@keyframes background-color {
100% {
background-color: #4791d0;
}
}
</style>
<button class="btn btn-primary">Register</button>
We need to animate an element that replicates the movement of a ball being juggled. So far we have learnt about " linear" ( red element) and "ease-out" (blue element) cubic bezier curves; however none of them depicts the juggling movement accurately; therefore we need to customize a bezier curve.
Note that the animation-timing-function
automatically reapplies at every key-frame. Since we have a key-frame in the middle of our animation duration, we will have two identical animation progressions at the upward and downward movement of the ball.
To simulate a juggling movement, we will be using a cubic bezier curve configuration similar to the following:
cubic-bezier(0.3, 0.4, 0.5, 1.6);
Notice that the value of y2 is larger than 1. Although the cubic bezier curve is mapped on an 1X1 coordinate system, and it can only accept x values from 0 to 1, the y value can be set to larger than one which results in a bouncing movement that is ideal for simulating the juggling ball.
Apply the above mentioned cubice bezier curve to the green element to see it in effect.
Change value of the animation-timing-function of the element with the id green
to a cubic-bezier function with x1, y1, x2, y2 values set respectively to 0.311, 0.441, 0.444, 1.649.
assert($('#green').css('animation-timing-function') === 'cubic-bezier(0.311, 0.441, 0.444, 1.649)'), 'message: Set the value of the <code>animation-timing-function</code> property of the element with the id <code>green</code> to a <code>cubic-bezier</code> with x1, y1, x2, y2 values set respectively to 0.311, 0.441, 0.444, 1.649 .');
<style>
.balls{
top:249px;
position: fixed;
width: 50px;
height: 50px;
top: 60%;
animation-name: jump;
animation-duration: 2s;
animation-iteration-count: infinite;
}
#red{
background:red;
left:25%;
animation-timing-function: linear;
}
#blue{
background:blue;
left:50%;
animation-timing-function: ease-out;
}
#green{
background:green;
left:75%;
animation-timing-function: cubic-bezier(.69,.1,1,.1);
/** Only change code above this line. **/
}
@keyframes jump{
50% {
top:10%;
}
}
</style>
<div class="img-circle balls" id= "red"></div>
<div class="img-circle balls" id= "blue"></div>
<div class="img-circle balls" id= "green"></div>
<style>
.balls{
top:249px;
position: fixed;
width: 50px;
height: 50px;
top: 60%;
animation-name: jump;
animation-duration: 2s;
animation-iteration-count: infinite;
}
#red{
background:red;
left:25%;
animation-timing-function: linear;
}
#blue{
background:blue;
left:50%;
animation-timing-function: ease-out;
}
#green{
background:green;
left:75%;
animation-timing-function: cubic-bezier(0.311, 0.441, 0.444, 1.649);
/** Only change code above this line. **/
}
@keyframes jump{
50% {
top:10%;
}
}
</style>
<div class="img-circle balls" id= "red"></div>
<div class="img-circle balls" id= "blue"></div>
<div class="img-circle balls" id= "green"></div>
@ahmadabdolsaheb wow - these Bezier curve animations are blowing my mind. Thank you for creating these challenges.
@atjonathan excellent work on the hover state button challenge. Keep it up. We're almost done with this topic :)
@QuincyLarson, would you please tell me what front we are using for our logo? Also in animation, key frame, and bezier curve challenges such as this, champers are introduced to animation properties and they use them to complete the challenges. I was wondering if creating the following challenge would be beneficial to campers? _Animate Elements using the CSS Animate Property_ :)
@ahmadabdolsaheb yes - we are using Sax Mono.
And yes - I agree that first creating a challenge that introduces the CSS Animate Property would be best. I've added it to the list of challenges above! :) Can you design this challenge as well?
@ahmadabdolsaheb actually, how would this be different from Create movement using CSS Animation?
@QuincyLarson not that different. :)
@ahmadabdolsaheb OK - we can just leave it as it is, then. Less work for you :)
We may want to resequence these challenges once we finish them all - that way we can make sure Create movement using CSS Animation is where it needs to be :)
@QuincyLarson, sure I will take care of that :)
By manipulating different selectors and properties, you can make interesting shapes. One of the easier ones to try is a moon shape. For this challenge we need to work with the box-shadow
property that sets the shadow of an element and the border-radius
property that controls the roundness of the element's corners.
We will create a round transparent object with a crisp shadow that is slightly offset to the side.
In order to create a round object the border-radius
should be set to only value that is 50%.
On the other hand, we should set offset-x | offset-y | blur-radius | spread-radius | color value of the box-shadow
in the given order.
We should insert a number as a value for the x and y offset, and set the blur-radius and spread-radius to 0 to get a crisp shadow that is the same size of the main element and at the end insert a color as a value.
Let's manipulate the square element we have to arrive to a moon shape.
Set the background-color
to transparent
, set the border-radius
property to 50% and for the box-shadow
property, set offset-x to 25px, offset-y to 10px, blur-radius to 0, spread-radius to 0, and color to blue
.
assert($('.center').css('background-color') === 'transparent'), 'message: Set the value of the <code>background-color</code> property to <code>transparent</code>.');
assert($('.center').css('border-radius') === '50%'), 'message: Set the value of the <code>border-radius</code> property to <code>50%</code>.');
assert($('.center').css('box-shadow') === '25px 10px 0 0 blue'), 'message: Set the value of the <code>box-shadow</code> property to 25px for offset-x, 10px for offset-y, 0 for blur-radius, 0 for spread-radius, and finally `blue` for color value');
<style>
.center
{
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
border-radius: 0px;
box-shadow: 25px 10px 10px 10px green;
}
</style>
<div class = "center"></div>
<style>
.center
{
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100px;
height: 100px;
background-color: transparent;
border-radius: 50%;
box-shadow: 25px 10px 0 0 blue;
}
</style>
<div class = "center"></div>
One of the most popular shapes in the world is the heart shape and we are going to make it in raw css in this challenge. But we need to familiarize ourselves with :before
and :after
selectors first. These selectors are used to to add something to before/after a selected element. In the following example a :before
selector is used to add a rectangle to an element with the class heart
:
.heart:before {
content: "";
background-color: yellow;
border-radius: 25%;
position: absolute;
height: 50px;
width: 70px;
top: -50px;
left: 5px;
}
Note that for the before and after selectors to function properly, they must have a defined content
property to contain contents such as photos and strings; however, since we will only use the before and after selectors to add shapes, we will set the content property to an empty string.
In the above example, the element with the id heart
has a :before
selector that produces a yellow rectangle with height and width of 50px and 70px. This rectangle has round corners due to its 25% border radius and is positioned absolutely at 5px from the left and 50px above the with element with the heart
class.
Let's transform the element on the right of the screen to a heart.
Start by changing the background-color
and border-radius
of the after
selector to pink
and 50%
respectively.
Now all we need to do is to use the before
selector to make a round shape, move the shape up and rotate the the element with the class heart
45 degrees to the left.
To Do
background-color
and border-radius
of the after
selector to pink
and 50%
respectively.heart
-45 degrees using the transform
property and rotate
function.heart
by using a before
selector.:before
selector, set its content
property to an empty string, background color to pink, border raduis to 50%, position to absolote
, width and height to 50px, and it should be located -25px from the top and 0px from the left;assert($('.heart').css('transform') === 'rotate(-45deg)'), 'message: transform the element with the id `heart` -45 degrees.');
assert($('.heart:after').css('background-color') === 'pink'), 'message: set the background-color property of the `:after` selector to pink .');
assert($('.heart:after').css('border-radius') === '50%'), 'message: set the border radios of the `:after` selector to 50% .');
assert($('.heart:before').css('content') === ''), 'message: set the content of the `:before` selector to an empty string.');
assert($('.heart:before').css('background-color') === 'pink'), 'message: set the background-color property of the `:before` selector to pink.');
assert($('.heart:before').css('border-radius') === '50%'), 'message: set the border radius of the `:before` selector to 50%.');
assert($('.heart:before').css('height') === '50px '), 'message: height of the `:before` selector should be 50px.');
assert($('.heart:before').css('width') === '50px '), 'message: width of the `:before` selector should be 50px.');
assert($('.heart:before').css('position') === 'absolute'), 'message: set the position of the `:before` selector to absolute .');
assert($('.heart:before').css('top') === '-25px'), 'message: set the shape of the `:before` selector -25px from the top.');
assert($('.heart:before').css('left') === '0'), 'message: set the shape of the `:before` selector 0px from the top.');
<style>
.heart {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: pink;
height: 50px;
width: 50px;
}
.heart:after {
content: "";
background-color: blue;
border-radius: 25%;
height: 50px;
position: absolute;
width: 50px;
left: 25px;
top: 0;
}
</style>
<div class = "heart"></div>
<style>
.heart {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: pink;
height: 50px;
transform: rotate(-45deg);
width: 50px;
}
.heart:before {
content: "";
background-color: pink;
border-radius: 50%;
height: 50px;
position: absolute;
width: 50px;
top: -25px;
left: 0;
}
.heart:after {
content: "";
background-color: pink;
border-radius: 50%;
height: 50px;
position: absolute;
width: 50px;
left: 25px;
top: 0;
}
</style>
<div class = "heart"></div>
@QuincyLarson, do you have anything specific in mind for the following challenges? I am trying to find good challenge ideas. _Use the box-shadow z-axis and Opacity together to Animate an Element_ _Create a Pattern by Reusing a Block of Elements_
@ahmadabdolsaheb I don't have anything specific ideas about these. These were ideas that I think @JonathanZWhite suggested we implement. If you can't think of any good ideas for them, I say move on to other sections where we could still use help: https://github.com/FreeCodeCamp/CurriculumExpansion/issues/46 (like D3)
And we can call this section a wrap for now :)
line-height
of a paragraph until the paragraph is properly spacedChallenge Description
In CSS, we can use
line-height
to change the height of each line in a paragraph.
Set the
line-height
of ourp
tag to25px
.
Challenge Seed
<style>
</style>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
</p>
Challenge Tests
assert($('p').css('display') == 'flex', 'message: Your <code>p</code> tag should have the <code>line-height</code> of <code>25px</code>.')
Challenge Solution
<style>
p {
line-height: 25px;
}
</style>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
</p>
I am writing some tests for challenges with keyframes, but I am having trouble selecting a property at a specific keyframe to check its value in assert(). For example:
.ball
animation-name: jump;
}
@keyframes jump{
50% {
top: 5px;
}
}
If possible, could you please tell me how to check the value of the top
property at the 50% keyframe to see if it is equal to 5px in assert()?
@atjonathan is in charge of coordinating the expansion of these challenges, but he needs your help.
For each challenge, please reply to this GitHub issue with:
Final Challenges List:
Challenges using a Bootstrap Card (consistent)
text-align
propertywidth
Propertyheight
Propertyheight
of an elementhr
Elementbackground-color
property of text.box-shadow
.Challenges based on position
Challenges based on color
Challenges based on typography
font-weight
of header 1–5 tags.line-height
of a paragraph until the paragraph is properly spacedUngrouped challenges
color
of an Anchor TagChallenges based on Animation