SVG and CSS create realistic cloud effects
In Greek mythology, Zeus created the Cloud Fairy Nefere. Like other Greek myths, this story is quite bizarre. Here is a short and suitable version:
According to legend, Neferele was created by Zeus in the image of his beautiful wife. A mortal met Nefere and fell in love with her. Together they... In the end, incredible that this cloud gave birth to a half-man and half-male centaur baby.
Very strange, right? I personally can't understand. Fortunately, the process of creating clouds in a browser is much simpler and more serious.
Recently, I found that developer Yuan Chuan has implemented a realistic cloud effect generated by code. For me, this effect that was implemented in the browser was once a myth.
Just browse this sample code and we can imagine that by using<filter></filter>
CSS box-shadow
of elements (including two SVG filters) can achieve a convincing single cloud effect.
The realistic effect we want is achieved through the clever combination of feTurbulence
and feDisplacementMap
. These SVG filters are powerful, complex and offer very exciting features (including an Oscar-winning algorithm!). However, its underlying complexity can be daunting.
While the physics of SVG filters are beyond the scope of this article, there is a lot of documentation available on MDN and w3.org. Very helpful pages about feTurbulence
and feDisplacementMap
are available for free (and as a chapter in this wonderful book).
In this article, we will focus on learning how to use these SVG filters to achieve amazing results. We don’t need to get a deeper look at how the algorithms behind the scenes work, just as artists don’t need to understand the molecular structure of pigments to render amazing landscapes.
Instead, let's keep an eye on several SVG properties that are crucial to drawing convincing clouds in your browser. Using these properties, we can use these powerful filters with ease and learn how to customize them accurately in our projects.
Start with the basics
There are five values ??worth paying attention to in the CSS box-shadow
attribute:
<code>box-shadow:<offsetx><offsety><blurradius><spreadradius><color> ;</color></spreadradius></blurradius></offsety></offsetx></code>
Let's turn these values ??up (probably higher than any sensible developer would use) so that the shadow itself becomes a character on the stage.
<code>#cloud-square { background: turquoise; box-shadow: 200px 200px 50px 0px #000; width: 180px; height: 180px; } #cloud-circle { background: coral; border-radius: 50%; box-shadow: 200px 200px 50px 0px #000; width: 180px; height: 180px; }</code>
Have you ever played or seen shadow dramas?
Just like changing the shape with your hands to change the shadow, the "source shape" in our HTML can be moved and deformed to move and change the shape of the shadow rendered in the browser. box-shadow
copies the original size and "transform" functionality on border-radius
. SVG filters are applied to elements and their shadows at the same time.
<code><svg height="0" width="0"><filter><feturbulence basefrequency=".01" numoctaves="10" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="10"></fedisplacementmap></filter></svg></code>
This is the markup for our current SVG. It won't render because we haven't defined any visuals (not to mention zero width and height). Its sole purpose is to save a filter, which we provide to our SourceGraphic
(that is, ours<div> ). Our Source<code><div> Its shadows are distorted independently by the filter. We will add the necessary CSS rules, linking the HTML element ( <code>#cloud-circle
) to the SVG filter using its ID:
<code>#cloud-circle { filter: url(#filter); box-shadow: 200px 200px 50px 0px #fff; }</code>
Look!
OK, admit it, adding SVG filters is quite inconspicuous.
don’t worry! We just touched the surface and there were a lot of good things to see.
Experiment feDisplacementMap
scale
property
Performing some non-scientific experiments on this attribute can produce dramatic effects. For the moment, let's keep all values ??in feTurbulence
unchanged, just adjust scale
property of DisplacementMap
.
As scale
value increases (in 30 increments), our source<div> Distortions occur and shadows are cast to reflect the random form of clouds in the sky.<pre class="brush:php;toolbar:false"><code><fedisplacementmap in="SourceGraphic" scale="180"></fedisplacementmap></code></pre>
<p> OK, we have made some progress! Let's change the color a little to create a more convincing cloud effect and enhance it.</p>
<pre class="brush:php;toolbar:false"> <code>body { background: linear-gradient(165deg, #527785 0%, #7FB4C7 100%); } #cloud-circle { width: 180px; height: 180px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 200px 200px 50px 0px #fff; }</code></pre>
<p> Now we are closer to the realistic cloud effect!</p>
<h3> Modify the <code>blur
value of box-shadow
The following series of images shows the effect of blur
value on box-shadow
. Here, the blur
value increases in 10 pixels increments.
To give our clouds some cumulus-like effect, we can broaden our source slightly<div> .<pre class="brush:php;toolbar:false"> <code>#cloud-circle { width: 500px; height: 275px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 200px 200px 60px 0px #fff; }</code></pre>
<p> etc! We widened the source element, and now it blocks the white shadow we call clouds. Let's "re-cast" the shadows to a longer distance so that our clouds are not obscured by the source image. (Imagine removing your hands from the wall so that you won't block the shadow drama's view.)</p>
<p> This can be easily achieved with some CSS positioning.<code><div> It is the parent element of the cloud and is statically positioned by default. Let's use some absolute positioning to transfer our source<code><div> "Pull" it up and remove the document stream. Initially, this will also reposition our shadows, so we also need to increase the distance between the shadows and slightly adjust the position of the element.<pre class="brush:php;toolbar:false"> <code>#cloud-circle { width: 500px; height: 275px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 400px 400px 60px 0px #fff; /* 增加陰影偏移量*/ position: absolute; /* 將父元素移出文檔流*/ top: -320px; /* 向下移動*/ left: -320px; /* 向右移動*/ }</code></pre>
<p> Yes! We have already got a pretty convincing cloud.</p>
<p> The images rendered into the browser depict the clouds quite well - but, I'm not sure... Can this cloud really reflect the cloud fairy Neferre? I believe we can do better!</p>
<h3 id="Express-depth-using-layers"> Express depth using layers</h3>
<p> This is what we want:</p>
<p> Judging from the depth, texture and richness of the clouds in this photo, one thing is clear: Zeus attended the art school. At least, he must have read The Universal Principles of Design, which expounds a powerful and seemingly ordinary concept:</p>
<blockquote><p> […] Lighting deviation plays an important role in the interpretation of depth and sense of nature and can be operated in various ways by the designer…using the contrast between light and dark areas to change the appearance of depth.</p></blockquote>
<p> This passage provides us with a clue on how we can greatly improve the cloud code we generate ourselves. We can render clouds that are highly similar to those in the reference image by stacking layers of different shapes, sizes, and colors together. This just requires calling our filter multiple times as needed. </p>
<pre class="brush:php;toolbar:false"><code><svg height="0" width="0"><filter><feturbulence basefrequency="0.012" numoctaves="4" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="170"></fedisplacementmap></filter><filter><feturbulence basefrequency="0.012" numoctaves="2" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="150"></fedisplacementmap></filter><filter><feturbulence basefrequency="0.012" numoctaves="2" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="100"></fedisplacementmap></filter></svg></code></pre>
<p> Applying our layers will give us the opportunity to explore <code>feTurbulence
and achieve its versatility. We will select the smoother type available: fractalNoise
and turn numOctaves
up to 6.
<code><feturbulence basefrequency="n" numoctaves="6" type="fractalNoise"></feturbulence></code>
what does that mean? Now, let's focus on baseFrequency
property. Here is the result we get when we increase the value of n:
Words such as turbulence , noise , frequency , and octave can appear strange or even confusing. But don't worry! Comparing the effect of this filter to sound waves is actually completely accurate. We can associate low frequencies ( baseFrequency=0.001
) with low noise and high frequencies ( baseFrequency=0.1
) with higher, clearer tones.
We can see that for cumulus-like effects, the value of baseFrequency
may comfortably lie in the ranges of ~0.005 and ~0.01.
Add details using numOctaves
Incrementing numOctaves
allows us to render images with extremely fine details. This requires a lot of calculations, so be aware that high values ??can seriously affect performance. Try to avoid increasing this value unless your browser is wearing a helmet and knee pads.
The good news is that we don't need to adjust this value too high to produce detail and fineness. As shown in the above image, we can set the numOctaves
value to 4 or 5.
The results are as follows
Use seed
attribute to achieve infinite changes
There is a lot to be said about seed
attribute because it hints at the magic happening behind the scenes. However, for our purpose, the utility of seed
can be summarized in four words: "different values, different shapes".
The Perlin noise function (mentioned earlier) uses this value as the starting point for its random number generator. Selecting not to include this property will default seed
to zero. However, if this property is included, no matter what value we assign to seed
, we don't need to worry about performance issues.
The above GIF represents some of the features provided by seed
. Remember that each cloud is a layered composite cloud. (Although I've adjusted the properties of each layer, I keep their respective seed
values ??consistent.)
Here, carefully looking at the reference image, I have already put 3 clouds<div> (Different opacity) superimpose on a base<code><div> superior. By trial and error and inputting arbitrary <code>seed
values, I ended up with a shape similar to the shape of a cloud in the photo.
Impressive
Of course, think we draw on the browser<div> Neferele who would be better than Zeus would be arrogant. However, the more mysteries we are able to dig out from CSS and SVG filters, the more we are able to create something visually amazing and highly similar to Thor’s original creation. Then, we can continue to conduct further experiments!<p> Reflected mist</p>
<p> High-rise cirrus cloud</p>
<p> In this article, we are just dabbing in a sea of ??power and complexity. SVG filters usually look overwhelming and inaccessible.</p>
<p> However, like the examples in the A Single Div project or Diana Smith's drawing skills, a relaxed and pleasant method of experiment always brings amazing results!</p>
<h4 id="Achievement-unlocks-Neferre-Cloud-Generator"> Achievement unlocks! Neferre Cloud Generator</h4>
<p> I believe many of you would be happy to dig deep into all the technical details needed to make clouds, but might prefer some more convenient ways to use clouds in your project. I developed a gadget to help generate clouds and experiment with shapes and changes.</p>
<p> Generate clouds!</p>
<p> Have any questions, suggestions or comments? Please contact me on Twitter or leave a comment in this post.</p>
<p> <small>Thank you very much to Amelia Bellamy-Royds for your valuable suggestions on this article.</small></p>
</div>
The above is the detailed content of Drawing Realistic Clouds with SVG and CSS. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

There are three ways to create a CSS loading rotator: 1. Use the basic rotator of borders to achieve simple animation through HTML and CSS; 2. Use a custom rotator of multiple points to achieve the jump effect through different delay times; 3. Add a rotator in the button and switch classes through JavaScript to display the loading status. Each approach emphasizes the importance of design details such as color, size, accessibility and performance optimization to enhance the user experience.

To deal with CSS browser compatibility and prefix issues, you need to understand the differences in browser support and use vendor prefixes reasonably. 1. Understand common problems such as Flexbox and Grid support, position:sticky invalid, and animation performance is different; 2. Check CanIuse confirmation feature support status; 3. Correctly use -webkit-, -moz-, -ms-, -o- and other manufacturer prefixes; 4. It is recommended to use Autoprefixer to automatically add prefixes; 5. Install PostCSS and configure browserslist to specify the target browser; 6. Automatically handle compatibility during construction; 7. Modernizr detection features can be used for old projects; 8. No need to pursue consistency of all browsers,

Use the clip-path attribute of CSS to crop elements into custom shapes, such as triangles, circular notches, polygons, etc., without relying on pictures or SVGs. Its advantages include: 1. Supports a variety of basic shapes such as circle, ellipse, polygon, etc.; 2. Responsive adjustment and adaptable to mobile terminals; 3. Easy to animation, and can be combined with hover or JavaScript to achieve dynamic effects; 4. It does not affect the layout flow, and only crops the display area. Common usages are such as circular clip-path:circle (50pxatcenter) and triangle clip-path:polygon (50%0%, 100 0%, 0 0%). Notice

Themaindifferencesbetweendisplay:inline,block,andinline-blockinHTML/CSSarelayoutbehavior,spaceusage,andstylingcontrol.1.Inlineelementsflowwithtext,don’tstartonnewlines,ignorewidth/height,andonlyapplyhorizontalpadding/margins—idealforinlinetextstyling

Setting the style of links you have visited can improve the user experience, especially in content-intensive websites to help users navigate better. 1. Use CSS's: visited pseudo-class to define the style of the visited link, such as color changes; 2. Note that the browser only allows modification of some attributes due to privacy restrictions; 3. The color selection should be coordinated with the overall style to avoid abruptness; 4. The mobile terminal may not display this effect, and it is recommended to combine it with other visual prompts such as icon auxiliary logos.

To create responsive images using CSS, it can be mainly achieved through the following methods: 1. Use max-width:100% and height:auto to allow the image to adapt to the container width while maintaining the proportion; 2. Use HTML's srcset and sizes attributes to intelligently load the image sources adapted to different screens; 3. Use object-fit and object-position to control image cropping and focus display. Together, these methods ensure that the images are presented clearly and beautifully on different devices.

Different browsers have differences in CSS parsing, resulting in inconsistent display effects, mainly including the default style difference, box model calculation method, Flexbox and Grid layout support level, and inconsistent behavior of certain CSS attributes. 1. The default style processing is inconsistent. The solution is to use CSSReset or Normalize.css to unify the initial style; 2. The box model calculation method of the old version of IE is different. It is recommended to use box-sizing:border-box in a unified manner; 3. Flexbox and Grid perform differently in edge cases or in old versions. More tests and use Autoprefixer; 4. Some CSS attribute behaviors are inconsistent. CanIuse must be consulted and downgraded.

The choice of CSS units depends on design requirements and responsive requirements. 1.px is used for fixed size, suitable for precise control but lack of elasticity; 2.em is a relative unit, which is easily caused by the influence of the parent element, while rem is more stable based on the root element and is suitable for global scaling; 3.vw/vh is based on the viewport size, suitable for responsive design, but attention should be paid to the performance under extreme screens; 4. When choosing, it should be determined based on whether responsive adjustments, element hierarchy relationships and viewport dependence. Reasonable use can improve layout flexibility and maintenance.
