Keywords: DOM, Math.random, arrow functions, const, animations, svg, intervals, positioning
This lesson will try to wrap up many of the concepts we have seen until now, taking each of them a step further.
CSS concepts:
The :root pseudo-class matches the root element of a document; :root is mostly used to store CSS variables.
Declaring a custom property is done using a custom property name that begins with a double hyphen (--), and a property value that can be any valid CSS value.
:root {
--main-bg-color: brown;
}
.main {
background-color: var(--main-bg-color);
}
-webkit is a CSS vendor prefix used for properties and features that are specific to the WebKit browser engine. Vendor prefixes are added to experimental or non-standard CSS properties and features by browser vendors to allow developers to use and test them before they become part of the official CSS specification.
Each element in HTML has a native display, some follow the normal flow of the document, some are inline elements (e.g. span, i, em, etc) and so on.
Display | Property | Usage |
---|---|---|
Block | display: block; |
Any block element generates a new line. |
Inline | display: inline; |
It takes space as much as the content requires; they don't generate a new line. |
Inline-block | display: inline-block; |
Behaves like a block but does not generate a new line. |
Flex | display: inline-flex/flex; |
Display properties related to flexbox; |
When using CSS, properties usually apply regardless of display type. A few exceptions:
In general, if you need to apply specific dimensions, positioning, or other layout-related properties to
an element, it's best to use display: block;
, display: inline-block;
Gradients in CSS are a way to create smooth color transitions between two or more colors within a single element's background or other properties that accept images. Gradients are generated using the linear-gradient() or radial-gradient() functions, which create an image consisting of a continuous blend of colors.
Linear gradients: A linear gradient transitions colors along a straight line. The linear-gradient() function takes multiple arguments: the direction (angle or keywords) and two or more color stops. The direction defines the angle at which the gradient progresses, and the color stops determine the colors and their relative positions within the gradient.
In this example, the gradient starts at the bottom left corner of the element (45 degrees) and transitions from red to yellow and then to blue.
.background {
background-image: linear-gradient(45deg, red, yellow, blue);
}
Radial gradients: A radial gradient transitions colors in a circular or elliptical pattern, radiating from a center point. The radial-gradient() function takes multiple arguments: the shape and size (optional), the position (optional), and two or more color stops. The shape can be circle or ellipse, and the size can be defined using keywords or explicit dimensions. The position determines the center of the gradient.
.background {
background-image: radial-gradient(circle at center, red, yellow, blue);
}
CSS animations can start as very simple and become very complex depending on the design's needs.
Animations can be as trivial as making some image bigger on hover to change completely the appearance of a page.
The main elements to create an animation with are:
animation: animation-name time behaviour
@keyframes animation-name {from {} to{}}
.example-1 {
background-color: red;
animation: example 4s infinite;
}
@keyframes example {
from {background-color: red;}
to {background-color: yellow;}
}
In this case, the animation changes the color from red to yellow. The animation property to the div of class example-1 specifies that the animation lasts 4s and it must be repeated infinitely. You can also see that CSS fills in any movement or color in between by itself.
.example-2 {
background-color: red;
animation: example-2 4s infinite;
}
@keyframes example-2 {
0% {background-color: red;}
50% {background-color: yellow;}
100% {background-color: red;}
}
In this second example, by using percentages, we make the bg-color go from red to yellow back to red, to have a smoother transition between the two colors.
Apart from color, we can also animate images. In this context, it is often better to use SVGs. This is a good explanation on how this works.
In this example, transform-origin: center;
fixes the animation to its center point; if we try to inspect the element, we can see that it is
actually a box, which moves along its center axis like a wheel. The animation also states that
it must have a linear behaviour, and the animation must go on forever.
The animation name, rotate-circle
, has a behavior that uses the rotate function
(native) which starts from 360dg and goes on until 0. By using a simple Javascript function that
changes the style innerHTML with the opposite starting points, we can go from clockwise to
counter-clockwise.
.rotating-circle {
transform-origin: center;
animation: rotate-circle 10s linear infinite;
}
@keyframes rotate-circle {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
CSS gives lots of possibilities to create different animations, but sometimes they may be not so intuitive to understand. If we want to animate the color of a text snippet, it may be not immediate to think that we must create a background, animate it, and then make the text transparent, and the surrounding background filled.
This example shows exactly this case.
:root {
--purple: rgb(123, 31, 162);
--violet: rgb(103, 58, 183);
--pink: rgb(244, 143, 177);
--bblack: rgb(10, 10, 10);
}
@keyframes background-pan {
from {
background-position: 0% center;}
to {
background-position: -200% center;
}
}
body {
background-color: var(--bblack);
margin: 0px;
overflow: hidden;
}
h1 {
color: white;
font-family: "Helvetica";
font-size: clamp(2em, 2vw, 4em);
font-weight: 400;
margin: 0px;
padding: 20px;
text-align: center;
}
h1 > .magic {
animation: background-pan 3s linear infinite;
background: linear-gradient(to right, var(--purple), var(--violet), var(--pink), var(--purple));
background-size: 200%;
white-space: nowrap;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
In this case, we used:
background-clip
to make the background only
apply to the text, and then fill the text with transparent color using
text-fill-color
.background-pan
is an animation that goes from position 0 to -200%, so that
it moves from side to sideclamp() is a function that allows to specify a minimum, preferred, and maximum value for a property. It is useful for responsive designs.
clamp(minimum, preferred, maximum)
Have a look at the whole design on Codepen
By adding some Javascript and SVGs, we can complete the styling of this text animation.
First, we add three SVG stars, put them inside a span
element and give them the
"magic-star" class.
<span class="magic-star"> <svg viewBox="0 0 512 512"> <path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" /> </svg> </span>
Then, we style the stars so that they have a strict size, behave as block, have an absolute position and a variable-based position, and they can scale up and down based on height and width variables.
h1 > .magic > .magic-star {
--size: clamp(20px, 1.5vw, 30px);
animation: scale 700ms ease forwards;
display: block;
height: var(--size);
left: var(--star-left);
position: absolute;
top: var(--star-top);
width: var(--size);
}
Here comes JS: what we need is to change the stars position. First we must give a relative position to the span so that absolute works.
We create a function that generates a random number based on a minimu and maximum range.
// Function to generate a random number between 'min' and 'max'
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Then we initialize two variables
let index = 0;
let interval = 1000;
Based on these two, we create an animation function.
We need to change the property of the star so that its variables --star-left and --star-top are randomized each time.
We also need to reset the animation each time, and force the browser to re-calculate the element's properties.
function animate(star) {
// Set the star's left and top position randomly within the specified range
star.style.setProperty("--star-left", rand(-10, 100) + '%');
star.style.setProperty("--star-top", rand(-40, 80) + '%');
// Reset the star's animation
star.style.animation = 'none';
star.offsetHeight; // Force the browser to re-calculate the element's properties
star.style.animation = '';
}
Now the fun part: let's select all the starts, and create a list of them:
var stars = document.getElementsByClassName("magic-star");
In summary, this snippet sets an initial delay for each star's animation and then repeatedly animates each star with a 1-second interval. The IIFE is used to preserve the index value for each star in the loop.
// Loop through each star and set up the animation
for (var i = 0; i < stars.length; i++) {
// Use an immediately invoked function expression (IIFE) to preserve the index value
(function(index) {
// Set a delay for each star's initial animation
setTimeout(function() {
// Call the animate function for the current star
animate(stars[index]);
// Set an interval to repeatedly call the animate function for the current star
setInterval(function() {
animate(stars[index]);
}, 1000);
}, index * (interval / 3));
})(i);
}
We can see here the final animation. Thanks to Hyperplexed for the design recreation.
© Andrea Schimmenti & Fabio Vitali. TW 2022-2023.