<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ UX - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ UX - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 26 May 2026 04:43:27 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/ux/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Apply Academic Theories to Human-Centered Web Design [Full Handbook] ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever abandoned an app right at the sign‑up page? Or felt uneasy navigating a website because the buttons were scattered randomly, the colors clashed, and the layout felt confusing and unneces ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-apply-academic-theories-to-human-centered-web-design-handbook/</link>
                <guid isPermaLink="false">69fe29e9f239332df4f7cd02</guid>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ux design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UI Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ user experience ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MathJax ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Great John ]]>
                </dc:creator>
                <pubDate>Fri, 08 May 2026 18:22:33 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/d7621fda-83a6-460e-aa38-bce970d4a655.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever abandoned an app right at the sign‑up page? Or felt uneasy navigating a website because the buttons were scattered randomly, the colors clashed, and the layout felt confusing and unnecessarily complex?</p>
<p>Maybe you were asked to complete twenty fields in one go. You carefully filled everything out, hit Submit — and only then were you told that your password didn't meet some hidden, unspoken requirement. A requirement that was never communicated upfront.</p>
<p>Instead of helpful guidance, you were met with a vague message: “Invalid input." Invalid how, you wonder?</p>
<p>Required fields weren’t marked. There was no real‑time validation. No helpful red outline showing which field was wrong. Just a generic prompt telling you to “go back and correct missing information,” as if you’re supposed to magically know what the system wants.</p>
<p>So you scroll.</p>
<p>You search.</p>
<p>You guess.</p>
<p>And you're now getting frustrated.</p>
<p>The reason you're frustrated is simple: no one enjoys repeating a task they thought they had already completed — especially when the mistakes could've been prevented with clear guidance along the way.</p>
<p>You manage to fill in the form and you tap the Submit button.</p>
<p>Nothing happens.</p>
<p>No loading spinner.</p>
<p>No subtle animation.</p>
<p>No confirmation message.</p>
<p>No success screen.</p>
<p>Just silence. For a brief moment, you’re left wondering: Did it go through? So you tap again. And maybe… one more time.</p>
<p>At this point, you become fed up and you either postpone the signup process to when you have the time, or you may not ever return.</p>
<p>Even if you haven’t experienced this exact scenario, you’ve almost certainly felt the same kind of friction: that moment when a digital interface makes you pause, hesitate, or wonder what you’re supposed to do next.</p>
<p>These frustrations often arise because frontend developers either overlook or are unaware of the essential design principles and theories that underpin a smooth, intuitive user experience.</p>
<p>As a frontend developer, your interface should minimise cognitive load, provide immediate clarity, and guide users effortlessly through every task.</p>
<p>In this handbook, I'll introduce the academic theories that should inform and elevate your frontend decisions.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-10-fittss-law">1.0 Fitts’s Law:</a></p>
<ul>
<li><p><a href="#heading-11-use-padding-wisely">1.1 Use padding wisely</a></p>
</li>
<li><p><a href="#heading-12-use-infinite-targets">1.2 Use infinite targets</a></p>
</li>
<li><p><a href="#heading-design-takeaway-from-fitts-law">Design Takeaway from Fitts Law:</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-20-hicks-law">2.0 Hick's Law:</a></p>
<ul>
<li><a href="#heading-design-takeaway-from-hicks-law">Design Takeaway from Hick's Law</a></li>
</ul>
</li>
<li><p><a href="#heading-30-gestalt-principles">3.0 Gestalt Principles:</a></p>
<ul>
<li><p><a href="#heading-key-gestalt-principles">Key Gestalt Principles:</a></p>
</li>
<li><p><a href="#heading-31-proximity">3.1 Proximity</a></p>
</li>
<li><p><a href="#heading-32-similarity">3.2 Similarity</a></p>
</li>
<li><p><a href="#heading-33-continuity">3.3 Continuity</a></p>
</li>
<li><p><a href="#heading-34-closure">3.4 Closure</a></p>
</li>
<li><p><a href="#heading-35-figureground">3.5 Figure/Ground</a></p>
</li>
<li><p><a href="#heading-36-common-fate">3.6 Common Fate</a></p>
</li>
<li><p><a href="#heading-37-focal-point">3.7 Focal Point</a></p>
</li>
<li><p><a href="#heading-design-takeaways-from-the-gestalt-principles">Design Takeaways from the Gestalt Principles</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-40-von-restorff-effect-the-isolation-effect">4.0 Von Restorff Effect (The Isolation Effect):</a></p>
<ul>
<li><a href="#heading-design-takeway-from-von-restorff">Design takeway from Von Restorff</a></li>
</ul>
</li>
<li><p><a href="#heading-50-jakobs-law">5.0 Jakob’s Law</a></p>
<ul>
<li><a href="#heading-design-takeaway-from-jakobs-law">Design Takeaway from Jakob's Law</a></li>
</ul>
</li>
<li><p><a href="#heading-60-millers-law">6.0 Miller’s Law</a></p>
<ul>
<li><a href="#heading-design-takeaway-from-millers-law">Design Takeaway from Miller's Law</a></li>
</ul>
</li>
<li><p><a href="#heading-70-the-goal-gradient-hypothesis">7.0 The Goal-Gradient Hypothesis</a></p>
<ul>
<li><a href="#heading-design-takeaway-from-goal-gradient-hypothesis">Design Takeaway from Goal-Gradient Hypothesis</a></li>
</ul>
</li>
<li><p><a href="#heading-80-zeigarnik-effect">8.0 Zeigarnik Effect</a></p>
<ul>
<li><a href="#heading-design-takeaway-from-zeigarnik-effect">Design Takeaway from Zeigarnik Effect</a></li>
</ul>
</li>
<li><p><a href="#heading-90-teslas-law">9.0 Tesla’s Law:</a></p>
<ul>
<li><a href="#heading-design-takeaway-from-teslas-law">Design Takeaway from Tesla's Law</a></li>
</ul>
</li>
<li><p><a href="#heading-100-peak-end-rule">10.0 Peak End Rule:</a></p>
<ul>
<li><a href="#heading-design-takeaway-from-peak-end-rule">Design takeaway from Peak End Rule</a></li>
</ul>
</li>
<li><p><a href="#heading-110-postels-law">11.0 Postel’s Law:</a></p>
<ul>
<li><a href="#heading-design-takeaway-from-postels-law">Design Takeaway from Postel's Law</a></li>
</ul>
</li>
<li><p><a href="#heading-120-doherty-threshold">12.0 Doherty Threshold:</a></p>
<ul>
<li><a href="#heading-design-takeaways-from-doherty-threshold">Design Takeaways from Doherty Threshold</a></li>
</ul>
</li>
<li><p><a href="#heading-130-serial-position-effect-primacy-and-recency">13.0 Serial Position Effect (Primacy and Recency):</a></p>
<ul>
<li><a href="#heading-design-takeaways-serial-position-effect">Design Takeaways Serial Position Effect</a></li>
</ul>
</li>
<li><p><a href="#heading-140-occams-razor">14.0 Occam’s Razor:</a></p>
<ul>
<li><a href="#heading-design-takeaway-from-occams-razor">Design Takeaway from Occam's Razor</a></li>
</ul>
</li>
<li><p><a href="#heading-150-parkinsons-law">15.0 Parkinson's Law</a></p>
<ul>
<li><a href="#heading-design-takeaway-for-parkinsons-law">Design Takeaway for Parkinson's law</a></li>
</ul>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a href="#heading-references">References</a></p>
</li>
</ul>
<p>You might wonder what academic theories have to do with frontend development.</p>
<p>The answer is simple. Academic theories aren't abstract ideas. There are the result of rigorous scientific investigation — controlled experiments, validated models, and decades of research into how humans think, learn, perceive, and interact with information.</p>
<p>Because these theories are grounded in evidence rather than opinion, they offer reliable guidance for building interfaces that align with how the human brain actually processes information.</p>
<p>Applying them to frontend development means you're not designing by guesswork or personal preference. Instead, you're applying tested, scientific insights to create clearer, faster, more humane user experiences.</p>
<p>In other words, when you build with academic theory in mind, your frontend becomes more than just visually appealing — it becomes cognitively efficient, behaviourally aligned, and measurably easier for users to navigate.</p>
<p>You can use the following laws and principles to guide your development work. Let’s start by looking at Fitt’s law.</p>
<h2 id="heading-10-fittss-law"><strong>1.0 Fitts’s Law:</strong></h2>
<p>Fitts’s law is the brainchild of Paul Fitts. He was among the early psychologists who recognised that many human errors result from flawed design rather than simple human weakness.</p>
<p>During World War II, he studied airplane cockpit layouts and concluded that numerous incidents attributed to pilot error were actually caused by poor design decisions (Hall, 2023; Budiu, 2022).</p>
<p>Here's the formula:</p>
<p>$$T = a + b \cdot \log_2\left(1 + \frac{D}{W}\right)$$</p>
<p>T = Movement Time</p>
<p>D = Distance to the target</p>
<p>W = Width (size) of the target</p>
<p>a, b = Empirically determined constants</p>
<p>Based on his findings, Fitts postulated that the time required to acquire/reach a target is determined by the distance to the target and the size of the target.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/7d2699bd-4878-4ab0-8669-21616cb8faf1.png" alt="7d2699bd-4878-4ab0-8669-21616cb8faf1" style="display:block;margin:0 auto" width="691" height="244" loading="lazy">

<p><em>Fig 1.0: Illustration of Fitts Law.</em></p>
<p>From the above, between Target B and Target C, it will be faster to interact with Target C than Target B simply because of the distance (Target B is farther away). Interestingly, though Target A and Target C are at the same distance, Target C will still be faster to interact with and less error-prone because of its larger size.</p>
<p>In simple terms, Fitt’s Law tells us that the time required to move to a target depends on two main factors: the distance to the target and the size of the target. The farther away an element is, the longer it takes to reach. The smaller it is, the more precision it demands, which increases the interaction time and the likelihood of errors.</p>
<p>Conversely, closer and larger targets reduce cognitive load, motor effort, and frustration.</p>
<p>In a nutshell, Fitts’s main message to developers is to reduce the distance users must travel on the screen and to make important buttons large and visually dominant.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/bc293949-cadc-46b2-892d-bdfa1dfc6db3.jpg" alt="bc293949-cadc-46b2-892d-bdfa1dfc6db3" style="display:block;margin:0 auto" width="928" height="664" loading="lazy">

<p><em>Fig 1.1: Showing Call-to-Action buttons are the largest and most visually prominent elements on each screen.</em></p>
<p>From the image above, you can see that the Call-to-Action buttons on each of the screens are the most visually dominant button and largest in size. They're also placed within the natural region. This makes them faster/easier to interact with.</p>
<p>You should also place your Call-to-Action button within the natural zone. This is a zone on a mobile phone where it's easy to reach with the thumb (as most people use their thumbs to select things on a phone screen). Here's a diagram showing the "natural zone" on a typical smartphone. It's much faster for a user to interact within the "natural zone" than the "hard zone" (see figure).</p>
<img src="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/e98d8d91-b4e6-4b4a-96e5-2524a6e09028.png" alt="e98d8d91-b4e6-4b4a-96e5-2524a6e09028" style="display:block;margin:0 auto" width="1536" height="1024" loading="lazy">

<p><em>Fig 1.2: Showing three different zones for buttons placement (natural, stretching and hard region)</em></p>
<h3 id="heading-11-use-padding-wisely">1.1 Use Padding Wisely</h3>
<p>Fitts' law can be applied to your development by increasing padding wisely. You can also use padding to increase the interactive area. By doing this, you're increasing the size of the targets.</p>
<p>This is important, because imagine a menu that disappears the moment your cursor drifts a few inches away. You’re weren't trying to close it — you simply moved slightly, and suddenly the entire menu collapses. That tiny slip forces you to start the interaction all over again. It’s a small mistake, but it creates a disproportionately frustrating experience.</p>
<p>This happens because the interactive area is too narrow.</p>
<p>That’s why effective padding — or more broadly, generous interactive zones — is essential. By increasing the clickable or hoverable area around a menu, you are increasing the size of the targets, which makes the interaction more stable, more forgiving, and far less cognitively demanding.</p>
<p>This ensures users can move naturally without fear of accidentally “falling off” the target.</p>
<h3 id="heading-12-use-infinite-targets">1.2 Use Infinite Targets</h3>
<p>Another fundamental principle that emerges from Fitt’s Law is the idea of infinite targets. When an interface element is placed at the very edge or corner of a screen, it becomes effectively “infinite” because the cursor can't move beyond the screen boundary. The edge acts as a physical barrier, allowing the user to fling the mouse in that direction without precision or careful aiming.</p>
<p>As a result, corners and edges become the fastest, easiest, and most reliable places for users to access important controls.</p>
<p>This is why operating systems such as Apple’s macOS and Microsoft Windows position their most essential menus and buttons at these locations. The macOS Apple Menu sits in the top‑left corner, Windows historically placed the Start button in the bottom‑left corner, and both systems anchor taskbars, docks, and notification areas along screen edges.</p>
<p>These placements reduce cognitive load, minimise motor effort, and increase interaction speed because users do not need to slow down or correct their cursor movement. The screen itself “catches” the pointer.</p>
<p>In essence, infinite targets transform small interface elements into large, easy‑to‑hit zones simply by leveraging the geometry of the screen.</p>
<p>What this means for you: place your most important and frequently used actions where users can reach them with the least effort. Screen edges and corners act as natural stopping points, meaning users can't overshoot them.</p>
<h3 id="heading-design-takeaways-from-fitts-law">Design Takeaways from Fitts Law:</h3>
<p><strong>Place Primary Actions Where the Task Ends:</strong><br>Placing a submit button at the top‑right forces users to travel all the way back after completing a long form. This increases interaction cost and breaks flow. The best place for a submit button is at the bottom of the form — exactly where the user finishes the task. This aligns with natural reading and interaction patterns.</p>
<p><strong>Keep Related Actions Physically Close:</strong><br>Separating “Add to Cart” and “Check Out” across opposite sides of the screen forces unnecessary thumb movement. Group related actions to reduce effort and speed up decisions.</p>
<p><strong>Make Primary Targets Large and Visually Dominant:</strong><br>Your main CTAs (“Subscribe Now,” “Pay Now,” “Create Account,” “Sign Up”) should be the most recognisable elements on the screen. Large, high‑contrast targets reduce errors and improve speed.</p>
<p><strong>Place High‑Value Actions at Screen Edges and Corners:</strong><br>Edges and corners act as “infinite targets” because the cursor can’t overshoot them. This makes them the fastest, easiest, and most reliable places for critical controls.</p>
<p>A tiny icon in the middle of the screen is hard to hit. The same icon placed at an edge becomes effectively huge because the boundary “catches” the pointer. Also, actions like navigation, primary CTAs, or global controls should live where users can reach them with minimal effort. Avoid burying important actions in the centre of the screen.</p>
<p><strong>Increase Target Size With Generous Padding:</strong><br>Small interactive zones force users to aim with pixel‑level precision. Adding padding expands the clickable or hoverable area, making interactions easier, faster, and more forgiving.</p>
<p><strong>Prevent Accidental “Fall‑Off” With Larger Hit Areas:</strong><br>Menus that collapse the moment the cursor drifts slightly create frustration. A wider interactive zone keeps the menu open during natural mouse movement, reducing accidental resets.</p>
<p>Users don’t move perfectly. Interfaces should accommodate slight slips without punishing them. Larger targets reduce cognitive load and eliminate unnecessary frustration. so by increasing the effective size of buttons, menus, and controls, you create interactions that feel stable and predictable, and users can move confidently without fear of losing their place.</p>
<p><strong>To Sum Up:</strong> The farther away an element is, the longer it takes to reach. The smaller it is, the more precision it demands, which increases the interaction time and the likelihood of errors. Conversely, closer and larger targets reduce cognitive load, motor effort, and frustration.</p>
<h2 id="heading-20-hicks-law"><strong>2.0 Hick's Law</strong>:</h2>
<p>Hick’s Law is a psychological principle that describes the relationship between the number of choices presented to a user and the time it takes them to make a decision. It was formulated by William Edmund Hick in 1952 (Yablonski, 2022; Proctor &amp; Scheider, 2018).</p>
<p>The law states that as the number of options increases, the decision time increases logarithmically. In simple terms, more choices slow users down, while fewer choices speed up decision-making.</p>
<p>$$T = a + b \cdot \log_2(n + 1)$$</p>
<p>Where:</p>
<p>T = time to make a decision,</p>
<p>n = number of choices,</p>
<p>b= a constant that depends on the task and the individual</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/d2c45f4b-77e9-42dc-a9c3-165dfe5f7ce7.jpg" alt="d2c45f4b-77e9-42dc-a9c3-165dfe5f7ce7" style="display:block;margin:0 auto" width="1136" height="692" loading="lazy">

<p><em>Figure 2.0 illustrates the relationship between user experience, reaction time, and the number of actions.</em></p>
<p>This is how users feel, for example, when they encounter a form that asks for too much information upfront. The longer the form gets, the more frustrated they become.</p>
<p>Examples of this are overloading menus with too many items, presenting long, unorganised forms, giving too many calls-to-action on one screen, and building nested menus with excessive depth.</p>
<p>All of these create friction and can lead to cognitive overload.</p>
<h3 id="heading-design-takeaway-from-hicks-law">Design Takeaway from Hick's Law</h3>
<p><strong>Avoid Overloading Users With Too Many Actions:</strong><br>Too many buttons, menu items, or choices at once increases cognitive load and slows decision‑making. Users freeze when everything competes for attention.</p>
<p><strong>Keep Navigation Clean and Focused:</strong><br>Cluttered menus hurt both usability and SEO. Search engines struggle to track overly complex navigation structures, and users struggle to find what matters.</p>
<p><strong>Use Progressive Disclosure to Reduce Complexity:</strong><br>Hide advanced or rarely used options under “More” or expandable sections. Reveal complexity only when the user needs it.</p>
<p><strong>Break Complex Tasks Into Smaller, Manageable Steps:</strong><br>Progressive disclosure works beautifully for multi‑step forms and decision flows. Smaller steps reduce overwhelm and improve completion rates.</p>
<p><strong>Group Related Options Into Logical Categories:</strong><br>Organising actions into meaningful clusters helps users process information faster. For example, placing “Edit” and “Delete” together leverages natural mental grouping.</p>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/mbYIfRxSkHs" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>

<p><em>Video 2.0: Video description of Progressive Disclosure.</em></p>
<p>From the video above, instead of showing all the menu details at once, it is better to hide them initially. As you can see, the additional information only appears when the arrow down button is pressed. This approach prevents overwhelming the user and keeps the interface clean and focused.</p>
<p>You should also reduce decision anxiety, as too many choices create doubt and friction (as they say, the more you ask from a user, the less you get).</p>
<p>Beyond this, try to use recommended labels, show brief descriptions, provide visual previews, and use comparison tables wisely to show comparison between products especially when they have many characteristics. An example of a comparison table is shown below:</p>
<p><a href="https://drive.google.com/file/d/1sY-tb9W1QDnyrH9dd3NSYsteP9WoMT27/view?usp=drive_link"><img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/5e52527a-3faf-4da1-97c2-a2a09ca7af8b.jpg" alt="Use of comparison table to compare products" style="display:block;margin:0 auto" width="1038" height="972" loading="lazy"></a></p>
<p><em>Figure 2.1: A comparison table being used to simplify complex information.</em></p>
<p>Also, rather than showing advanced configuration options by default, display only the most commonly used settings. Advanced options can be hidden under an expandable section like “Advanced” or “More Settings. This makes your interface less cluttered and more visually organized.</p>
<p>And speaking of visual organization, this is the perfect moment to introduce Gestalt principles — the psychological rules that explain how users naturally group and interpret what they see.</p>
<p><strong>To Sum Up</strong>: As the number of options increases, the decision time increases logarithmically.</p>
<h2 id="heading-30-gestalt-principles"><strong>3.0 Gestalt Principles</strong>:</h2>
<p>In the 1920s, a group of German psychologists – Max Wertheimer, Kurt Koffka, and Wolfgang Köhlern – introduced what are now known as the Gestalt Principles. Their work sought to understand how humans perceive and interpret visual information (Bustamante, 2023).</p>
<p>The word “Gestalt” is German for “unified whole,” reflecting the core idea behind the theory: people naturally perceive objects as organised patterns and complete forms rather than as separate, disconnected parts.</p>
<p>These principles explain how the human mind structures visual elements to make sense of the world. Over time, they have become highly influential in fields such as design, user experience (UX), psychology, and data visualization, where understanding perception is critical.</p>
<h3 id="heading-key-gestalt-principles">Key Gestalt Principles:</h3>
<h3 id="heading-31-proximity">3.1 Proximity</h3>
<p>Elements that are placed close to each other are perceived as a group, while those spaced far apart are seen as separate. This is why labels are placed directly next to their corresponding input fields.</p>
<p>For example: In a blog feed, the "Title," "Author," and "Date" should have small margins between them (8px), while the space between one blog post card and the next should be much larger (40px). This tells the user's brain: "These three text strings belong to this specific post."</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/b68ab7f4-1b2e-47f1-8e8c-8ae8f32198c1.jpg" alt="b68ab7f4-1b2e-47f1-8e8c-8ae8f32198c1" style="display:block;margin:0 auto" width="1046" height="956" loading="lazy">

<p><em>Fig 3:0 Illustration of proximity (Gestalt Principle)</em></p>
<p>From the fig above, the spacing within the blog feed plays a powerful role in how effortlessly users interpret what they see. When elements sit close together, the brain instinctively treats them as belonging to the same unit. This is why placing the author credit just 8px beneath the title creates an immediate mental link. The viewer doesn’t need to pause or decode who wrote which article; proximity does the cognitive work automatically, forming a tight, intuitive grouping.</p>
<p>Equally important is the generous 40px gap between individual cards. This larger spacing introduces “visual breathing room.” Without it, a feed can quickly collapse into a dense wall of text, overwhelming the user and discouraging exploration. The wider margin establishes a clear boundary—a natural stop-and-start rhythm—that makes each card feel distinct and the entire layout more scannable.</p>
<p>Finally, subtle spacing differences can guide behaviour, not just perception. The slightly larger 12px margin above the read‑more link separates it from the passive information above it. This spacing cues the user that the link represents an action rather than another piece of descriptive text. It’s a small adjustment, but it shifts the element’s role from informational to interactive, helping users understand what they can <em>do</em> next.</p>
<p>Together, these spacing decisions transform a simple list of posts into a structured, intuitive, and behaviourally clear interface—one where the user never has to think about the layout, because the layout is already thinking for them.</p>
<p>Proximity controls meaning: move elements closer to show connection, separate them to show difference.</p>
<h3 id="heading-32-similarity">3.2 Similarity</h3>
<p>We naturally group elements that share similar visual characteristics, such as color, shape, size, or orientation.</p>
<p>For example, even if buttons are spread across a page, if they're all the same shade of blue, the user understands they perform similar functions.</p>
<p>If your primary "Submit" button is blue with rounded corners, every other primary action on your site should look exactly the same. If you suddenly use a square red button for a primary action, the user will be confused because the "similarity" is broken.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/151d9658-5a4b-4d1d-b885-02c73c53cdbd.jpg" alt="151d9658-5a4b-4d1d-b885-02c73c53cdbd" style="display:block;margin:0 auto" width="1618" height="2170" loading="lazy">

<p><em>Fig 3:1 : illustration of similarity (Gestalt principle)</em></p>
<p>As you can see from above, the layout clearly demonstrates how the Gestalt Principle of Similarity works by showing two different visual situations: one where everything matches, and one where a single element breaks the pattern.</p>
<p>All three product cards share the same visual characteristics:</p>
<ul>
<li><p>Same card shape</p>
</li>
<li><p>Same border and shadow</p>
</li>
<li><p>Same image size and placement</p>
</li>
<li><p>Same blue “Add to Cart” button</p>
</li>
<li><p>Same font style and spacing</p>
</li>
</ul>
<p>Because these elements look alike, your brain automatically groups them as one category — “products that belong together.”<br>You don’t have to think about it; the similarity creates instant visual unity.</p>
<p>This is the Gestalt Principle of Similarity in action.</p>
<p>In the second row, everything is still similar except one button:</p>
<ul>
<li><p>The middle product’s button is orange, not blue</p>
</li>
<li><p>It has square corners, not rounded</p>
</li>
<li><p>The text is italic, not regular</p>
</li>
<li><p>The label changes to “Quick Buy”</p>
</li>
</ul>
<p>Because this button breaks the shared pattern, your brain immediately notices it and treats it as different or special.</p>
<p>Developers can use broken similarity to intentionally highlight featured items, promotions, or urgent actions.</p>
<p>When similarity is broken, the different element stands out and draws attention.</p>
<h3 id="heading-33-continuity">3.3 Continuity</h3>
<p>The human eye prefers to follow a continuous path or curve rather than jagged or broken lines. We perceive items aligned on a line or curve as being related. This is often used in navigation menus or horizontal carousels to guide the user's gaze.</p>
<p>For example, you might have a horizontal carousel where the last visible card is slightly "cut off" at the edge of the screen. This visual break creates a path that encourages the user to keep scrolling as their eyes follow the line of cards.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/e44556e8-4174-4073-9c05-63b5df9a1278.jpg" alt="e44556e8-4174-4073-9c05-63b5df9a1278" style="display:block;margin:0 auto" width="1650" height="214" loading="lazy">

<p><em>Fig 3:2: illustration of continuity (Gestalt principle)</em></p>
<p>As you can see, all four form fields — <em>First Name</em>, <em>Last Name</em>, <em>Email Address</em>, and <em>Phone Number</em> — are perfectly aligned along one continuous horizontal path. Because the human eye naturally prefers to follow an unbroken line, your gaze moves smoothly from left to right across the fields without effort.</p>
<p>The final field is slightly cut off at the edge, which creates a subtle visual cue that the line continues beyond the visible area. This encourages the user to keep scrolling or swiping, because their eyes are already following the direction of the form.<br>when elements are arranged along a straight path, curve, or flow, the brain automatically treats them as connected and expects the pattern to continue.</p>
<p>Another example is Instagram Stories, which are arranged in a smooth horizontal line at the top of the app. Instagram reinforces this by slightly revealing the next story circle at the edge of the screen. That tiny “peek” acts as a continuation cue — your eyes expect the line to keep going, so your finger follows.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/bb019a6d-33c9-4509-b1c7-191b5a453c46.jpg" alt="bb019a6d-33c9-4509-b1c7-191b5a453c46" style="display:block;margin:0 auto" width="1320" height="520" loading="lazy">

<p><em>Fig 3:3: illustration of continuity (Gestalt principle)</em></p>
<p>As you can see from above, all the circular story icons are arranged in a straight horizontal line, and your visual system instinctively follows that line from left to right without effort.</p>
<p>The slight visibility of the next story at the edge of the screen strengthens this effect, signaling that the sequence continues beyond what's currently shown. Also, because the icons share the same size, spacing, and shape, there are no visual interruptions, allowing your eyes to glide across them in one continuous motion.</p>
<p>This seamless flow is exactly what continuity describes: the tendency of the human eye to follow the direction of a line or pattern, assuming it continues even when part of it is out of view.</p>
<p>Continuity is the tendency of the human eye to follow the direction of a line or pattern, assuming it continues even when part of it is out of view.</p>
<h3 id="heading-34-closure">3.4 Closure</h3>
<p>Closure refers to the mind’s ability to perceive a complete, unified form even when parts of that form are missing. Rather than requiring every boundary, line, or shape to be explicitly drawn, the brain instinctively fills in the gaps. When used intentionally, closure allows interfaces to feel cleaner, more elegant, and more cognitively efficient.</p>
<p>When we look at a complex arrangement of visual elements, we tend to look for a single, recognisable pattern. If an image is missing parts, our brains fill in the gaps to "close" the shape.</p>
<p>One of the most celebrated examples of closure in visual identity design is the panda symbol used by the World Wide Fund for Nature (WWF). This logo demonstrates how strategic omission can produce a memorable, emotionally resonant, and universally recognisable mark.</p>
<p>At first glance, the panda illustration appears simple, composed of a few bold black shapes arranged against a white background.</p>
<p>Yet a closer look reveals that the panda is not fully drawn. There are no outlines defining the body, no complete contours around the head, and no explicit boundaries separating limbs from background. Instead, the designer uses a series of carefully placed shapes (ears, eye patches, nose, and partial limbs) to imply the rest of the animal. The viewer’s mind fills in the missing information, completing the silhouette effortlessly.</p>
<p>This is closure at its most effective: the brain constructs a whole from fragments, creating a sense of completeness without visual overload.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/0c40effd-e4d2-4669-af1d-56faac976b4a.jpg" alt="0c40effd-e4d2-4669-af1d-56faac976b4a" style="display:block;margin:0 auto" width="522" height="784" loading="lazy">

<p><em>Fig 3:4: illustration of closure (Gestalt principle)</em></p>
<p>For example, a "hamburger menu" (three lines) isn't a literal drawer, but our brains "close" the shape to understand it represents a menu.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/b67253cd-2a2c-4565-9818-f5586dad6d36.jpg" alt="b67253cd-2a2c-4565-9818-f5586dad6d36" style="display:block;margin:0 auto" width="1244" height="236" loading="lazy">

<p><em>Fig 3:5: illustration of closure (Gestalt principle)</em></p>
<p>An example of closure in practice can be seen in step indicators commonly used in checkout flows. These components often rely on partial shapes, implied boundaries, and incomplete outlines to guide the user through a sequence of actions.</p>
<p>For instance, upcoming steps may be represented by dashed circles. Although the circles aren't fully drawn, the viewer immediately recognises them as complete shapes. The brain resolves the missing segments, allowing the interface to communicate progression without heavy borders or fully rendered icons. This subtle use of closure reduces visual clutter while preserving clarity.</p>
<p>Closure refers to the mind’s ability to perceive a complete, unified form even when parts of that form are missing.</p>
<h3 id="heading-35-figureground">3.5 Figure/Ground</h3>
<p>This principle describes the mind's tendency to separate an object (the figure) from its surrounding area (the ground or background). In web design, using a "modal" or "pop-up" relies on this: by blurring the background, you force the user to see the pop-up as the focal figure.</p>
<p>When a user clicks "Login" on a modal/lightbox, the background site often dims (the "Ground") while the login box stays bright and centered (the "Figure"). This immediate depth change tells the user exactly where their attention belongs.</p>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/UCdjymjASOU" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>

<p><em>Video 3.5.0 Video description of Figure/Ground (Gestalt Principle)</em></p>
<p>From the video above, you can see that when the Quick View button is clicked, the selected figure stands out while the background darkens. This contrast guides the user’s attention and helps them focus on the figure. Developers can use this technique to direct users’ attention to what matters most or to what they want users to notice.</p>
<p>This principle describes the mind's tendency to separate an object (the figure) from its surrounding area (the ground or background).</p>
<h3 id="heading-36-common-fate">3.6 Common Fate</h3>
<p>Elements that move in the same direction are perceived as more related than elements that are stationary or move in different directions. Think of a dropdown menu: when all sub-items slide down together, they are clearly part of the same "unit."</p>
<p>For example, when you click a FAQ header and five sub-items slide down at the exact same speed and direction, the "Common Fate" tells the user that all those items belong to that specific category. If they flew in from different directions, the relationship would be lost.</p>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/T10xmlne6E4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>

<p><em>Video 3.6.1 Video description of common fate (Gestalt Principle)</em></p>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/5FncGLRy0bM" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>

<p><em>Video 3.6.2 Video description of common fate (Gestalt Principle)</em></p>
<p>From the video shown above, the e‑commerce animation example demonstrates these principles clearly by using two distinct motion patterns: a group of regular products that move upward together, and a pair of special‑category items that enter dramatically from the left. Through these contrasting movements, the interface communicates category differences without relying on text labels or explicit instructions.</p>
<p>Therefore, developers can use this motion‑based differentiation as a design strategy to guide users’ perception—allowing the interface to signal hierarchy, category structure, and product importance purely through animated behaviour rather than through static visual labels.</p>
<p>Elements that move in the same direction are perceived as more related than elements that are stationary or move in different directions.</p>
<h3 id="heading-37-focal-point">3.7 Focal Point</h3>
<p>Whatever stands out visually will capture and hold the viewer’s attention first. This is essentially the principle of emphasis. A bright "Sign Up" button in a sea of gray text acts as the focal point, directing the user's primary action.</p>
<p>For example, an alert banner or a pricing table should stand out from its surroundings. Beyond this, in a three-tier pricing table (Basic, Pro, Enterprise), the "Pro" column is often slightly larger or a different color. This creates a focal point that draws the eye to the "recommended" option immediately.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/711c9ee9-b546-4041-bf86-30c80154bd47.jpg" alt="711c9ee9-b546-4041-bf86-30c80154bd47" style="display:block;margin:0 auto" width="1784" height="646" loading="lazy">

<p><em>Fig 3:7: illustration of closure (Gestalt principle)</em></p>
<p>In visual interface design, the Gestalt principle of Focal Point plays a crucial role in directing user attention toward the most important element on a screen.</p>
<p>A focal point is created when one element breaks the established pattern of surrounding elements, making it stand out immediately.</p>
<p>In e‑commerce interfaces, this principle is often applied to highlight primary actions such as purchasing, subscribing, or upgrading. The “Buy Now” button provides a clear and practical example of how focal points function within a layout.</p>
<p>From the example above, the first two buttons share the same visual characteristics: neutral colours, and regular weight text. This repetition establishes a visual pattern that the user quickly becomes familiar with.</p>
<p>But the “Buy Now” button intentionally disrupts this pattern. It uses a bright colour, which contrasts sharply with the muted tones of the other buttons. This colour difference alone is enough to draw the eye, as humans are naturally sensitive to changes in hue and saturation within a uniform environment.</p>
<p>The Focal Point may sound like it's similar to the principle of Similarity, but the two operate in completely opposite ways within perceptual psychology.</p>
<p>Similarity explains how the mind naturally groups elements that share visual characteristics –&nbsp;such as colour, shape, or size – into coherent units. Once this grouping is established, the interface gains structure and predictability.</p>
<p>Focal Point, on the other hand, works by intentionally breaking that structure. Instead of reinforcing uniformity, it introduces a deliberate contrast – through colour, scale, brightness, or motion –&nbsp;to draw the viewer’s attention to one specific element.</p>
<p>In other words, Similarity creates the background pattern, while Focal Point identifies the one element that must stand out against that pattern.</p>
<p>Whatever stands out visually will capture and hold the viewer’s attention first.</p>
<h3 id="heading-design-takeaways-from-the-gestalt-principles">Design Takeaways from the Gestalt Principles</h3>
<p><strong>Use Spacing as Your Primary Grouping Tool:</strong><br>Elements that belong together should sit closer to each other than to anything else. Spacing communicates structure faster than borders or boxes. Use tight internal spacing (6–12px) for related items and wide external spacing (24–48px) to separate groups.</p>
<p><strong>Build a Strict, Consistent Visual System — and Stick to It:</strong><br>Define clear rules for button types, text styles, icon sizes, and alignment patterns. Consistent left‑aligned text blocks, predictable carousel lines, and stable flow patterns reduce cognitive load and make interfaces feel trustworthy.</p>
<p><strong>Guide the Brain With Spacing, Alignment, Consistency, Contrast, and Motion:</strong><br>The human brain is always trying to group, follow, and prioritise what it sees. Your job is to guide that instinct through intentional layout decisions, not fight against it.</p>
<h2 id="heading-40-von-restorff-effect-the-isolation-effect"><strong>4.0 Von Restorff Effect (The Isolation Effect)</strong>:</h2>
<p>This is the brainchild of Hedwig von Restorff, posited in 1933. In principle it states: An item that stands out is more noticable and more likely to be remembered than other items (Hunt, 1995).</p>
<p>So unique or visually distinct elements grab attention and are more memorable – in other words, distinctiveness dictates memory. When a user interacts with an interface, their brain naturally seeks patterns to minimize cognitive effort.</p>
<p>While consistency is generally a virtue in design, a perfectly uniform layout can lead to "banner blindness" or habituation, where the user stops noticing details.</p>
<p>By strategically breaking a pattern through changes in color, size, shape, or spacing, the developer can "isolate" an element, triggering a biological response that flags the item as high-priority.</p>
<p>Note that although the Focal Point principle may initially seem similar to the Von Restorff Effect, they describe two different psychological processes.</p>
<p>Focal Point is a Gestalt visual principle that explains how one element becomes the centre of attention within a composition because it carries the strongest visual contrast –&nbsp;through size, colour, brightness, position, or motion. Its purpose is to guide the viewer’s eye toward the most important element in the layout.</p>
<p>The Von Restorff Effect comes from cognitive psychology, not Gestalt theory. It states that an item that is noticeably different from a group of similar items is not only more attention‑grabbing but also more memorable.</p>
<p>So Focal Point is about where the eye goes first, while the Von Restorff Effect is about what the brain remembers later.</p>
<h3 id="heading-design-takeaways-from-von-restorff">Design takeaways from Von Restorff</h3>
<p><strong>Use Isolation to Make CTAs Impossible to Miss:</strong><br>On a page filled with neutral text and standard links, a single high‑contrast button (like a bold “Primary Blue” or “Emergency Red”) instantly becomes the standout element. This leverages the Von Restorff Effect to pull the user’s eye toward the most important action.</p>
<p><strong>Create a Visual “Hitch” in the Scan Path:</strong><br>A distinct CTA interrupts the user’s natural left‑to‑right, top‑to‑bottom scanning rhythm. This makes actions like “Buy Now” or “Sign Up” the first thing they notice and the last thing they forget.</p>
<p><strong>Make Critical Actions Visually Distinct:</strong><br>Because users naturally notice the one element that breaks a pattern, your most important actions should use deliberate contrast — color, size, shape, weight, or motion. Isolate key information instead of letting it blend into surrounding UI noise.</p>
<p><strong>Avoid Over‑Differentiation — or Nothing Stands Out:</strong> If every button is loud, animated, or uniquely styled, the interface becomes chaotic. The Von Restorff Effect only works when there is a clear, stable pattern — and you break it once, intentionally.</p>
<p><strong>To Sum Up:</strong> An item that stands out is more noticable and more likely to be remembered than other items.</p>
<h2 id="heading-50-jakobs-law"><strong>5.0 Jakob’s Law</strong></h2>
<p>Jakob’s Law states that users spend most of their time on other sites, so they expect your interface to behave like the ones they already know.</p>
<p>Familiar patterns — hamburger menus, top navigation, search icons, and clickable top‑left logos — reduce cognitive load because users don’t have to interpret anything new.</p>
<p>But while Jakob’s Law is foundational to UX, I think it can also unintentionally suppress innovation.</p>
<p>When developers over‑prioritise familiarity, they fall into a standardisation trap: endlessly optimising conventional patterns instead of exploring fundamentally better ones.</p>
<p>The Pie Menu is a perfect illustration of this. According to Fitts’s Law, the time required to reach a target depends on its distance and size. Linear menus place the last item much farther from the cursor than the first, creating uneven interaction costs.</p>
<p>Radial menus position every option at an equal distance from the centre, and their wedge‑shaped targets effectively grow larger as the pointer moves outward.</p>
<p>Mathematically, pie/radial menu are faster to interact with and more efficient — yet they remain rare in mainstream web design because they violate users’ expectations. In other words, Jakob’s Law keeps us locked into a familiar but suboptimal pattern simply because “that’s how it’s always been done.”</p>
<p>But the challenge is not choosing between familiarity and innovation, but balancing them.</p>
<p>This is where the Aesthetic–Usability Effect becomes powerful. Research shows that users perceive attractive interfaces as easier to use, and they are more forgiving of minor usability friction when the design is visually pleasing.</p>
<p>A beautifully crafted Pie Menu, for example, can encourage users to invest the small amount of learning required to use it. By applying aesthetic delight strategically, developers can introduce innovative patterns without overwhelming users.</p>
<p>The principle that emerges is simple: Be conventional where it matters, and innovative where it delights.</p>
<h3 id="heading-design-takeaway-from-jakobs-law">Design Takeaway from Jakob's Law</h3>
<p><strong>Keep Trust‑Critical Elements Predictable:</strong><br>Navigation, search, authentication, and other high‑stakes interactions must follow established conventions. Users rely on these patterns for speed, confidence, and safety — this is where Jakob’s Law should be respected without exception.</p>
<p><strong>Experiment Only in Low‑Risk, High‑Creativity Areas:</strong><br>In creative or productivity‑focused zones — like editing tools in a photo app — you can safely introduce new interaction models such as radial menus, gesture wheels, or context‑aware tool selectors. These areas invite exploration and benefit from efficiency‑driven innovation.</p>
<p><strong>To Sum Up:</strong> Be conventional where it matters, and innovative where it delights.</p>
<h2 id="heading-60-millers-law"><strong>6.0 Miller’s Law</strong></h2>
<p>Miller’s Law originates from George A. Miller’s classic paper “The Magical Number Seven, Plus or Minus Two.” It states that the average person can hold only about 7 (±2) chunks of information in working memory at any given moment (Miller, 1956).</p>
<p>Crucially, Miller emphasised that the brain doesn’t store isolated items — it groups them into meaningful units called chunks. Because working memory is so limited, developers must structure information in ways that respect this cognitive boundary.</p>
<p>This principle has direct implications for interface design. Long, unbroken strings of information overwhelm users, whereas chunked formats are far easier to process.</p>
<p>For example, instead of displaying a phone number as 1234567890, formatting it as 123‑456‑7890 transforms ten digits into three manageable chunks. The same logic applies to navigation: aim for five to nine primary menu items, and if you need more, group them into categories. Users remember the category as a single chunk rather than each individual link.</p>
<p>Miller’s Law also explains why long forms are so intimidating. When a user sees 30 fields on one page, their brain interprets it as a single, massive task — far beyond the 7±2 limit.</p>
<p>A progressive stepper solves this by breaking the form into smaller stages of 5–7 fields each. This reduces cognitive load, creates a sense of progress, and significantly lowers abandonment rates.</p>
<p>The same principle applies to product listings or search results. Expecting users to compare 50 items at once is unrealistic. Instead, provide strong filtering tools so users can narrow the set to a manageable size — ideally within the range their working memory can meaningfully evaluate.</p>
<p>In essence, Miller’s Law reminds developers that humans don’t process information in bulk. They process it in structured, meaningful chunks.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6998def93dc17c4862075045/3add2891-c6f8-4df1-a044-6cea6c5f1945.jpg" alt="Image of progressive stepper" style="display:block;margin:0 auto" width="818" height="960" loading="lazy">

<p><em>Fig 6.0: Illustrating progressive stepper</em></p>
<p>In the example above, the interface uses both a progress bar and a stepper to guide the user through multiple stages of a task. After completing the first page and selecting “Continue,” the user moves to the next step, and the progress bar updates accordingly. This creates a clear sense of forward movement and accomplishment.</p>
<p>By breaking the process into smaller segments, the interface prevents cognitive overload. If all the information were presented on a single page, users might feel overwhelmed, unsure where to begin, or discouraged by the sheer volume of work.</p>
<p>A step‑by‑step flow transforms a large task into a sequence of manageable actions, increasing the likelihood of completion.</p>
<h3 id="heading-design-takeaway-from-millers-law">Design Takeaway from Miller's Law</h3>
<p><strong>Respect the 7±2 Working‑Memory Limit:</strong><br>Users can only hold about seven chunks of information at once. Long, unbroken content overwhelms them, while chunked information is instantly easier to process.</p>
<p><strong>Chunk Information Into Meaningful Units:</strong><br>The brain doesn’t store isolated items — it groups them. Format data (like phone numbers), menus, and settings into clear, memorable chunks instead of long, flat lists.</p>
<p><strong>Keep Navigation Within 5–9 Primary Items:</strong><br>If you need more than nine options, group them into categories. Users remember the category as a single chunk, not each individual link.</p>
<p><strong>Break Long Forms Into Smaller Steps:</strong><br>A 30‑field form feels like one giant task. A progressive stepper with 5–7 fields per step keeps users below the cognitive overload threshold and dramatically reduces abandonment.</p>
<p><strong>Reduce Comparison Load With Strong Filters:</strong><br>Expecting users to compare 50 products at once is unrealistic. Provide filtering tools that shrink the decision set to something the working memory can actually handle.</p>
<p><strong>Design for Chunked Thinking, Not Bulk Processing:</strong><br>Humans don’t process information in bulk — they process structured, meaningful groups. Interfaces that respect this limitation feel lighter, faster, and more intuitive.</p>
<p><strong>To Sum Up:</strong> A step‑by‑step flow transforms a large task into a sequence of manageable actions, increasing the likelihood of completion.</p>
<h2 id="heading-70-the-goal-gradient-hypothesis">7.0 The Goal-Gradient Hypothesis</h2>
<p>This is the perfect moment to introduce the Goal‑Gradient Hypothesis, originally proposed by behaviorist Clark Hull in 1932 (Yablonski, 2022). The hypothesis states that people become more motivated as they get closer to achieving a goal. In other words, users naturally accelerate their engagement when they sense they are nearing completion.</p>
<p>This principle is incredibly powerful in UX design, especially for progress tracking, gamification, and reward systems.</p>
<p>The takeaway is straightforward: Because users are more motivated near the finish line, progress indicators should be prominent and meaningful.</p>
<p>Percentages, progress bars, and step counters reinforce momentum. Micro‑achievements — such as badges, checkmarks, or subtle confetti — amplify motivation by celebrating small wins.</p>
<p>Tasks should be broken into measurable milestones so users can see themselves advancing.</p>
<p>This is why e‑learning platforms display messages like “You’ve completed 8 of 10 lessons — almost there!” and why fitness apps highlight progress with prompts such as “3 km done, 2 km to go.” These cues leverage the goal‑gradient effect to keep users engaged, energized, and eager to finish.</p>
<p>By combining progressive steppers with clear progress feedback, developers create interfaces that feel lighter, more encouraging, and far more motivating — ultimately improving completion rates and overall user satisfaction.</p>
<p>But what happens when a goal isn't completed? Why do we sometimes feel uncomfortable leaving things unfinished? That discomfort is explained by another psychological principle called the Zeigarnik Effect — the tendency for people to remember and feel tension about incomplete tasks. We will look at this next.</p>
<h3 id="heading-design-takeaway-from-goal-gradient-hypothesis">Design Takeaway from Goal-Gradient Hypothesis</h3>
<p><strong>Make Progress Visible to Boost Motivation:</strong><br>According to the Goal‑Gradient Hypothesis, users naturally speed up as they sense they’re nearing completion. Prominent progress bars, percentages, and step counters tap into this instinct and keep momentum high.</p>
<p><strong>Celebrate Micro‑Achievements to Reinforce Engagement:</strong><br>Badges, checkmarks, subtle confetti, and “step completed” cues reward small wins. These micro‑rewards amplify motivation and make long tasks feel lighter and more achievable.</p>
<p><strong>Break Tasks Into Measurable Milestones:</strong><br>Users stay motivated when they can see themselves advancing. Divide complex flows into clear steps so progress feels tangible rather than overwhelming.</p>
<p><strong>Use Progress Feedback to Drive Completion:</strong><br>Messages like “8 of 10 lessons completed — almost there” or “3 km done, 2 km to go” leverage the goal‑gradient effect to energise users and pull them toward the finish line.</p>
<p><strong>Combine Steppers With Clear Feedback for Maximum Impact:</strong><br>Progressive steppers paired with strong visual feedback create interfaces that feel encouraging, structured, and motivating — dramatically improving completion rates.</p>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/-mDuFB3W2bg" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>

<p><em>Video 8.0 : Video illustrating goal gradient</em></p>
<p><strong>To Sum Up:</strong> People become more motivated as they get closer to achieving a goal.</p>
<h2 id="heading-80-zeigarnik-effect"><strong>8.0 Zeigarnik Effect</strong></h2>
<p>The Zeigarnik Effect is a psychological principle stating that people remember unfinished or interrupted tasks better than completed ones (Cherry, 2024).</p>
<p>Memory begins with sensory input, which is processed into short-term memory. Unfinished tasks persist in our thoughts, leading to active recall. This ongoing engagement can turn them into long-term memories, enhancing recall until resolved. This increases engagement, encourages task completion, improves retention, and drives conversions.</p>
<p>So because people remember unfinished tasks better than completed ones (Zeigarnik Effect), developers use progress indicators to make users aware that something is incomplete and motivate them to finish it.</p>
<p>In your designs, you can break long forms into multi-step processes to encourage completion and display profile completion percentages (for example, 70% complete) to push users toward 100%.</p>
<p>This is the main reason why e-commerce platforms send abandoned cart reminders to bring users back to complete their purchases. It's also why apps use streak systems to encourage daily engagement and habit formation and learning platforms show course completion bars to motivate users to finish modules.</p>
<h3 id="heading-design-takeaway-from-zeigarnik-effect">Design Takeaway from Zeigarnik Effect</h3>
<p><strong>Unfinished Tasks Stay Active in Memory — Use That to Drive Completion:</strong><br>Because incomplete tasks linger in working memory (Zeigarnik Effect), users naturally keep thinking about what they haven’t finished. This tension boosts recall, engagement, and the likelihood of returning to complete the task.</p>
<p><strong>Make Incompleteness Visible With Progress Indicators:</strong><br>Progress bars, percentages, and step counters remind users that something is still unfinished. This gentle psychological pressure motivates them to continue until the task is complete.</p>
<p><strong>Break Long Flows Into Multi‑Step Processes:</strong><br>A massive form feels overwhelming, but a stepper with smaller chunks keeps users moving. Showing “70% complete” nudges them toward finishing the last stretch.</p>
<p><strong>Use Reminders to Re‑activate Unfinished Intent:</strong><br>Abandoned cart emails, streak reminders, and “continue your lesson” prompts work because the unfinished task is already active in the user’s mind. The reminder simply pulls them back into the loop.</p>
<p><strong>Celebrate Completion to Close the Cognitive Loop:</strong><br>Checkmarks, confirmations, and completion badges give users closure. This resolves the mental tension created by the unfinished task and reinforces positive behaviour.</p>
<p><strong>To Sum Up:</strong> Unfinished tasks persist in our thoughts, leading to active recall.</p>
<h2 id="heading-90-teslers-law"><strong>9.0 Tesler’s Law</strong>:</h2>
<p>This law was proposed by Lawrence Tesler. He was a computer scientist known for his work on human-computer interaction, and he contributed significantly to making software more user-friendly, including work on cut, copy, and paste functionality.</p>
<p>This law is otherwise known as the Law of Conservation of Complexity. The core Idea here is every process has a certain amount of “inherent complexity" that can't be removed. You can only decide who handles it: the user or the system.</p>
<p>Some examples of these inherent complexities might be:</p>
<ul>
<li><p>translating user actions into correct operations behind the scenes,</p>
</li>
<li><p>handling unreliable or slow network connections,</p>
</li>
<li><p>connecting with third-party APIs, services, or legacy systems,</p>
</li>
<li><p>sorting large datasets quickly,</p>
</li>
<li><p>performing complex search operations</p>
</li>
<li><p>managing version changes and compatibility issues,</p>
</li>
<li><p>managing state, interactions, and animations without confusing the user.</p>
</li>
</ul>
<p>All of these can be inherently complex, but it's the job of the developer to deal with the complexity.</p>
<p>As a developer, you should always try as much as possible to push complexity to the system. For example, instead of making a user type their full address manually, use an Auto-complete API (Google’s Places and Map is best for this). The complexity of finding and validating the address still exists, but the software handles the work for them.</p>
<p>Here's a practical example: let’s say you're designing a student platform that requires users to enter their university name. A practical approach would be to store an array of all universities in the UK in your codebase (This is the hard part Tesla hinted at).</p>
<p>As the user types, they don't need to enter the full name, and their full university name is shown (relating to what they have typed). For instance, if they intend to type “University of Sheffield,” simply typing “Sheff” should prompt the system to display the full university name, which they can then select.</p>
<p>In Dart, you can use a package like fuzzysearch to implement this kind of intelligent matching.</p>
<p>The advantage of this approach is greater than it first appears. It improves data consistency because users often enter the same information in different ways. For example, some users might type “Uni of Sheff,” others “Sheffield University,” and others “Uni of Sheffield,” while all are referring to “University of Sheffield.”</p>
<p>This is how messy data is created, and it creates more work for data analysts. Little wonder that data analysts spend up to 70% of their time cleaning data.</p>
<p>If developers invested more time in structuring how data is collected to ensure consistency, there would be far less work downstream for analysts. This same logic should be applied in how we collect date, time, and other information.</p>
<p>So apart from people's names and email addresses, you should try to standardize the data your app collects as much as possible. Use date and time pickers, stepper controls, input masks, checkboxes, dropdown menu and radio buttons, toggle switches. and so on.</p>
<p>The essence of removing complexity from the user is not only about improving usability, but also about ensuring that the data collected is standardised, structured, and consistent.</p>
<h3 id="heading-design-takeaway-from-teslers-law">Design Takeaway from Tesler's Law</h3>
<p><strong>Push Complexity to the System, Not the User:</strong><br>Every process contains unavoidable complexity. Your job is to handle it behind the scenes so the user experiences the simplest possible interaction.</p>
<p><strong>Automate Tasks Users Shouldn’t Have to Think About:</strong><br>Use tools like autocomplete, fuzzy search, intelligent defaults, and validation APIs to remove manual effort. The complexity still exists — but the system absorbs it instead of the user.</p>
<p><strong>Standardise Inputs to Prevent Messy Data:</strong><br>Users enter the same information in wildly different ways. Use pickers, dropdowns, input masks, radio buttons, and toggles to enforce consistent, structured data collection.</p>
<p><strong>Handle Inherent Technical Complexity Internally:</strong><br>Network issues, API quirks, large dataset sorting, search optimisation, state management, and animation logic are all developer responsibilities. Users should never feel this complexity.</p>
<p><strong>To Sum Up:</strong> Every process contains unavoidable complexity. Your job as a developer is to handle it behind the scenes so the user experiences the simplest possible interaction.</p>
<h2 id="heading-100-peak-end-rule"><strong>10.0 Peak End Rule</strong>:</h2>
<p>In 1993, Daniel Kahneman, Barbara Fredrickson, Charles Schreiber, and Donald Redelmeier invited volunteers into a lab for what sounded like a simple experiment. The task was straightforward: place a hand into a container of painfully cold water (Kahneman et al., 1993)</p>
<p>In the first round, participants kept their hand in 14°C water for 60 seconds. It was uncomfortable, sharp, and unpleasant but after one minute, it was over.</p>
<p>In the second round, they again endured 60 seconds in 14°C water. But this time, they were asked to keep their hand in for an extra 30 seconds. The temperature was raised slightly to 15°C. Still cold. Still unpleasant. Just slightly less intense.</p>
<p>Objectively, the second experience was worse. It lasted 90 seconds instead of 60. More total pain. More suffering.</p>
<p>Later, the researchers asked a simple question:</p>
<p>If you had to repeat one of the trials, which would you choose?” Surprisingly, most participants chose the longer one.</p>
<p>Why would anyone choose more pain?</p>
<p>The researchers realised something profound: people don’t remember experiences by calculating total discomfort. Instead, the mind summarizes the experience using just two key moments — the most intense point (the peak) and the final moment (the end).</p>
<p>In both trials, the peak pain was the same: 14°C. But the longer trial ended slightly better, at 15°C. That small improvement at the end reshaped how the entire episode was remembered. The participants’ “experiencing self” suffered more during the longer trial. But their “remembering self” preferred it because it ended on a less painful note.</p>
<p>From this, the researchers introduced what became known as the Peak–End Rule: we judge experiences largely by their most intense moment and how they finish, not by how long they last.</p>
<p>Since people largely judge an experience by how it ends, developers should focus on designing satisfying confirmation screens and smooth exit interactions. You should concentrate less on making every single moment perfect and instead prioritise optimising the peak and final moments.</p>
<p>A negative ending can overshadow an otherwise good experience, so carefully avoid frustrating final steps such as unexpected fees or confusing confirmations.</p>
<p>Emotional intensity strongly shapes memory, which is why many apps incorporate celebration animations, rewards, or success messages at key moments to leave a lasting positive impression.</p>
<h3 id="heading-design-takeaway-from-peak-end-rule">Design takeaway from Peak End Rule</h3>
<p><strong>People Judge Experiences by the Peak and the Ending — Not the Total Duration:</strong><br>Users don’t remember every moment. They remember the most intense point and how the experience ends. A slightly better ending can completely reshape how the entire interaction is remembered.</p>
<p><strong>Prioritise Strong, Positive Endings in Your UX Flows:</strong><br>A smooth final step, a clear confirmation, or a satisfying success screen leaves a disproportionately strong impression. A bad ending can overshadow an otherwise great experience.</p>
<p><strong>Design for Emotional Peaks at Key Moments:</strong><br>Celebration animations, rewards, checkmarks, and success messages create memorable emotional spikes. These peaks anchor the experience in the user’s memory.</p>
<p><strong>Don’t Try to Perfect Every Moment — Perfect the Right Moments:</strong><br>Optimise the peak and the end of the journey. These two moments define how users recall the entire interaction.</p>
<p><strong>Avoid Negative Surprises at the Finish Line:</strong><br>Unexpected fees, confusing confirmations, or friction at the last step can ruin the memory of the whole process. Protect the ending carefully.</p>
<p><strong>To Sum Up:</strong> We judge experiences largely by their most intense moment and how they finish, not by how long they last.</p>
<h2 id="heading-110-postels-law"><strong>11.0 Postel’s Law</strong>:</h2>
<p>Jon Postel’s famous principle – “Be conservative in what you send, be liberal in what you accept” –&nbsp; is a philosophy of kindness in software design. At its core, the principle argues that systems should be generous with what they accept from users, yet disciplined and predictable in what they output.</p>
<p>When developers follow this approach, users feel supported and understood. When they don’t, users feel punished for being human.</p>
<p>A user’s input is rarely perfect. People type quickly, make mistakes, follow their own habits, or rely on formats familiar to them. A robust system embraces this reality. It accepts messy, human input and quietly transforms it into clean, standardized data.</p>
<p>Real people don't think in strict formats. They write dates the way they learned in school, type phone numbers the way they say them aloud, and enter names and addresses in whatever structure feels natural to them.</p>
<p>A rigid system will reject anything that doesn’t match its narrow expectations, but a robust system, by contrast, adapts to the user.</p>
<p>Consider dates. A brittle interface might demand MM/DD/YYYY and reject everything else. A more humane system accepts a wide range of formats — “1 May 2024,” “2024‑05‑01,” “05/01/24,” or “May 1st, 2024” — and quietly converts them into a standard internal representation. This is where the complex handling described by Tesla's Law comes into play (Shifting complexity to the system, rather than the user).</p>
<p>Phone numbers follow the same pattern. People might enter (555) 123 4567, 555‑123‑4567, 5551234567, or +1 555 123 4567. A fragile system throws errors. A robust one parses all of them using libraries like libphonenumber and moves on.</p>
<p>Addresses are equally varied. “221B Baker St,” “221‑B Baker Street,” and “221 Baker St., Apt B” all refer to the same place. A forgiving system normalizes these instead of rejecting them.</p>
<p>Even names can be surprisingly complex. Hyphens, apostrophes, multiple words, and titles are all part of real human identity. Rejecting “O’Connor,” “Jean‑Luc,” or “Dr. Sarah Lee” is not just technically incorrect — it's disrespectful to the user.</p>
<p>Search bars offer another clear example. A strict search bar demands perfect spelling and exact phrasing. A robust one handles typos (“restuarant”), partial words (“resta”), synonyms (“food places”), and natural language (“where can I eat nearby”). It meets the user where they are instead of forcing them to think like a machine.</p>
<p>Currency should be normalized to a clear format such as GBP 5.00, no matter whether the user typed “£5,” “5 pounds,” or “5 GBP.”</p>
<p>Even file uploads benefit from standardization: whether the user uploads .jpeg, .jpg, .JPG, or .JPEG, the system should store everything as .jpg.</p>
<p>Error messages follow the same principle. Vague feedback like “Invalid password” leaves users confused and frustrated.</p>
<p>A clear, conservative message — “Incorrect password. Please try again.” — respects the user’s time. And instead of hiding password requirements, the system should state them upfront: minimum eight characters, at least one uppercase letter, at least one number.</p>
<p>Predictability reduces friction.</p>
<p>Because users inevitably make mistakes or enter data in unexpected ways, developers should design input fields that are tolerant rather than brittle. This means accepting flexible formats, offering autocorrect or intelligent parsing, and using forgiving validation rules that interpret the user’s intent instead of rejecting their effort.</p>
<p>Clear instructions, tooltips, and visible requirements should appear before submission so users understand what the system expects without trial and error.</p>
<p>When errors do occur, the interface should handle them gently—never crashing, and never forcing the user to start over.</p>
<p>Even simple variations, such as phone numbers typed with spaces, dashes, or parentheses, should be accepted and normalized behind the scenes.</p>
<p>By embracing flexibility on the input side and clarity on the output side, developers create systems that feel humane, resilient, and respectful of the way real people actually behave.</p>
<h3 id="heading-design-takeaway-from-postels-law">Design Takeaway from Postel's Law</h3>
<p><strong>Accept Messy Human Input, Output Clean Structured Data:</strong><br>Users type dates, names, phone numbers, and addresses in unpredictable ways. A humane system accepts this variability and quietly normalises it into a consistent internal format.</p>
<p>Rigid interfaces punish users for being human. Robust interfaces interpret intent — handling typos, partial matches, synonyms, and natural language without complaint.</p>
<p>Also accept variations in spacing, punctuation, casing, and structure. Let users type naturally — the system should handle the complexity, not them.</p>
<p><strong>Be Flexible With Input, Be Strict With Output:</strong><br>This is the heart of Postel’s Law. Let users express information naturally, but ensure your system stores and displays it in a predictable, standardised way.</p>
<p><strong>Use Intelligent Parsing and Autocorrection to Reduce Errors:</strong><br>Libraries like libphonenumber, fuzzy search, and natural‑language parsers allow systems to accept a wide range of formats while still producing clean, reliable data.</p>
<p><strong>Normalise Everything Behind the Scenes:</strong><br>Dates, phone numbers, currency, file extensions, and addresses should all be standardised internally. This prevents messy data and reduces downstream cleanup work.</p>
<p><strong>Provide Clear, Predictable Feedback:</strong><br>Error messages should be specific and helpful. Requirements should be visible upfront. Users should never be surprised, confused, or forced to start over.</p>
<p><strong>Combine Postel’s Law With Tesler’s Law:</strong><br>Shift complexity to the system. Intelligent handling of messy input reduces cognitive load, improves usability, and ensures consistent, high‑quality data.</p>
<p><strong>To Sum Up:</strong> A rigid system will reject anything that doesn’t match its narrow expectations, but a robust system, by contrast, adapts to the user.</p>
<h2 id="heading-120-doherty-threshold"><strong>12.0 Doherty Threshold</strong>:</h2>
<p>The Doherty Threshold is a principle in human–computer interaction which proposes that systems should respond quickly enough to keep users actively engaged (Mod 2024).</p>
<p>When response times stay below a certain limit, users remain focused and productive. But once performance already meets this optimal responsiveness level, making the system even faster or adding extra capability doesn't significantly enhance satisfaction or efficiency.</p>
<p>The idea was introduced by Walter J. Doherty in 1976 in his paper “A Comparison of Programming Systems and Doherty Threshold.” His research showed that maintaining rapid system feedback fast enough to sustain continuous interaction has a stronger impact on productivity than simply increasing system power or features beyond that point.</p>
<p>Doherty proposes that this shouldn't be greater than 400ms Rule: If the system responds within this window, the user feels in total control. If the response takes longer, the user's attention begins to wander, and their "train of thought" is broken.</p>
<p>The challenge, of course, is that not every operation can realistically complete within 400ms. Some tasks require heavy computation, large network calls, or complex rendering. This is where the concept of perceived performance becomes essential.</p>
<p>Even when the system can't finish the work quickly, it can feel fast by responding instantly at the UI level. Developers can achieve this illusion of speed through a combination of thoughtful design patterns and disciplined engineering practices.</p>
<p>On the technical side, performance begins with reducing unnecessary work. Keeping the number of HTML elements low helps the browser render faster. Rendering only the visible portion of long lists prevents the Document Oject Model (DOM) from becoming bloated. Splitting scripts and deferring non‑critical code ensures that essential interactions load first.</p>
<p>Using CSS transforms and opacity changes avoids expensive layout recalculations. Lazy‑loading images, videos, and scripts ensures that the interface becomes interactive long before all assets are downloaded.</p>
<p>These optimizations don’t just improve raw speed — they create the foundation for interfaces that feel responsive.</p>
<h3 id="heading-design-takeaways-from-doherty-threshold">Design Takeaways from Doherty Threshold</h3>
<p><strong>Instant Feedback</strong>: When a user clicks a button, provide a visual change (like a button press animation or a spinner) immediately, even if the background task takes longer.</p>
<p><strong>Skeleton Screens</strong>: Use placeholder blocks that mimic the layout of the page while data loads. This makes the app feel like it is responding instantly.</p>
<p><strong>Progressive Loading</strong>: Load text and basic structures first, then "pop in" high-resolution images later.</p>
<p><strong>Optimistic UI</strong>: When a user hits "Save," don't wait for the server. Update the UI instantly (Doherty) and handle the "messy" data formatting on the backend (Postel).</p>
<p><strong>Live Inline Validation</strong>: Show a green checkmark or a helpful error message as the user types. This keeps them below the 400ms "thought-break" limit.</p>
<p><strong>Debouncing</strong>: In search bars, start showing results after a few keystrokes so the user feels the app is "predicting" their needs.</p>
<p><strong>To Sum Up:</strong> When response times stay below a certain limit, users remain focused and productive. But once performance already meets this optimal responsiveness level, making the system even faster or adding extra capability doesn't significantly enhance satisfaction or efficiency.</p>
<h2 id="heading-130-serial-position-effect-primacy-and-recency"><strong>13.0 Serial Position Effect (Primacy and Recency)</strong>:</h2>
<p>Murdock’s study investigated how the position of a word in a list affects recall, known as the serial position effect. He presented 103 psychology students with lists of 10 to 40 words, one at a time, at either 1 or 2 seconds per word (McLeod, 2025).</p>
<p>Participants were divided into six groups, each experiencing a different combination of list length and presentation rate, and were asked to recall as many words as possible in any order.</p>
<p>The results showed that participants were most likely to remember words at the beginning of the list (primacy effect) and at the end of the list (recency effect), while words in the middle were recalled less often. The recency effect persisted even in longer lists, and the middle section of the recall curve formed a flat asymptote.</p>
<p>Murdock explained this using the multi-store model of memory: early words were rehearsed and transferred to long-term memory, last words remained in short-term memory, and middle words were neither sufficiently rehearsed nor retained, leading to poorer recall.</p>
<p>The experiment demonstrated that memory performance varies systematically with the position of information in a sequence.</p>
<p>This is the reason why the most important information or actions should never be buried in the middle.</p>
<p>As a developer, you should put your most critical navigation links (like "Home" or "Dashboard") at the far left or the top of a list. In a pricing table, put the most popular or recommended plan on the Place "Final Actions" (like "Log Out," "Cart," or "Support") at the end of a menu or the far right of a navigation bar.</p>
<p>In a long onboarding flow, put the most exciting benefit of the app on the very last slide so the user enters the app feeling motivated.</p>
<p>Avoid placing highly important buttons in the middle of a row. If you have a row of 7 buttons, the user is statistically likely to overlook the 4th one.</p>
<h3 id="heading-design-takeaways-serial-position-effect">Design Takeaways <strong>Serial Position Effect</strong></h3>
<p><strong>Place Critical Items at the Beginning or End — Never the Middle:</strong><br>Users reliably remember the first and last items in any sequence (primacy and recency). Anything placed in the middle is statistically more likely to be forgotten or ignored. Also, actions such as “Log Out,” “Cart,” “Support,” or “Checkout” should sit at the far right or bottom — the natural recency position.</p>
<p><strong>Put Essential Navigation Links at the Far Left or Top:</strong><br>Links like “Home,” “Dashboard,” or “Overview” should appear at the start of a menu, where recall and recognition are strongest.</p>
<p><strong>To Sum Up:</strong> The results showed that participants were most likely to remember words at the beginning of the list (primacy effect) and at the end of the list (recency effect), while words in the middle were recalled less often.</p>
<h2 id="heading-140-occams-razor"><strong>14.0 Occam’s Razor</strong>:</h2>
<p>Although first articulated in the 14th century by the Franciscan friar William of Ockham, Occam’s Razor remains one of the most indispensable principles in a developer’s toolkit. In fact, skipping this law while discussing other theories and principles would be like skipping the glue that holds the entire framework together.</p>
<p>At its core, Occam’s Razor states that “among competing explanations, the simplest one is usually the best.”</p>
<p>For example, if two user interfaces achieve the same goal, the one with fewer visual elements is typically superior because it requires less processing power.</p>
<p>The fundamental takeaway for modern developers regarding Occam’s Razor is that complexity is a tax on the user’s cognitive resources.</p>
<p>In an era of information density, the developer's primary role is no longer to provide "more" features – rather, it's to curate the most direct path to a solution.</p>
<p>In practice, Occam’s Razor becomes a reminder to keep things as simple as possible. This “less is more” mindset shapes everything from navigation to forms.</p>
<p>A good rule for navigation is the Rule of Five: aim for three to five main menu items instead of a long, overwhelming list. This keeps choices clear and prevents users from freezing up when they see too many options.</p>
<p>The same idea applies to data entry. When you ask only for the information that truly matters, you respect the user’s time and reduce the chance of “form fatigue,” which is one of the biggest reasons people abandon sign‑ups or checkout flows.</p>
<p>Simplicity isn’t just elegant — it’s practical, humane, and far more effective.</p>
<h3 id="heading-design-takeaway-from-occams-razor">Design Takeaway from Occam's Razor</h3>
<p><strong>Choose the Simplest Effective Solution:</strong><br>When two designs achieve the same goal, the one with fewer elements is almost always better. Simplicity reduces cognitive load and speeds up user decision‑making.</p>
<p><strong>Simplicity Is Not Just Aesthetic — It’s Humane:</strong><br>Clear, minimal interfaces respect the user’s time, reduce friction, and make the product feel effortless. Simplicity is both a design strategy and an act of empathy.</p>
<p><strong>To Sum Up:</strong> Simplicity isn’t just elegant — it’s practical, humane, and far more effective.</p>
<h2 id="heading-150-parkinsons-law">15.0 Parkinson's Law</h2>
<p>Occam’s Razor teaches us to prefer the simplest solution that works. But why do we so often end up with complex systems in the first place? That tendency is explained by another principle: Parkinson’s Law.</p>
<p>Parkinson’s Law states that "work expands to fill the time available for its completion". In design, this means projects often become overly complex or take longer than necessary if given too much time, resulting in inefficient, over-designed, or cluttered interfaces.</p>
<p>In design, this manifests as Feature Creep. If you give yourself three months to build an app, you will spend three months adding "nice-to-have" animations, extra settings toggles, and niche edge cases that nobody asked for and in reality, what you have added isn’t that important.</p>
<p>You just succeeded in adding layers of complexity that might ends up violating some of the laws we spoke about. Occam’s Razor reminds us that the simplest solution is often the most effective.</p>
<p>By being aware of Parkinson’s Law and the tendency for work to expand, developers can manage their time intentionally and focus only on what truly matters.</p>
<h3 id="heading-design-takeaway-for-parkinsons-law">Design Takeaway for Parkinson's law</h3>
<p><strong>Set Clear Constraints to Keep Designs Focused:</strong><br>Intentional time limits and scope boundaries prevent over‑designing. Constraints force clarity, prioritisation, and simplicity.</p>
<p><strong>Build Only What Truly Matters for the User:</strong><br>Parkinson’s Law reminds you to resist the urge to fill time with unnecessary features. Focus on the core experience, not the edge cases nobody asked for.</p>
<p><strong>Use Occam’s Razor to Counterbalance Parkinson’s Law:</strong><br>As work expands, complexity grows. Occam’s Razor pulls you back to the simplest effective solution. Together, the two principles prevent bloated, over‑engineered products.</p>
<p><strong>To Sum Up:</strong> Work expands to fill the time available for its completion</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Human-centered design is deeply influenced by a set of psychological principles that explain how users perceive, process, and interact with digital systems.</p>
<p>Among these, Fitts’s Law establishes that the time required to acquire a target depends on its size and distance. In practice, this means that larger and closer elements are easier and faster to interact with.</p>
<p>To apply this in practice, developers should make primary call-to-action elements prominent, large, and easily reachable –&nbsp;especially in mobile interfaces where thumb accessibility is critical.</p>
<p>Closely related to decision-making is Hick’s Law, which states that the more choices a user is presented with, the longer it takes to make a decision. Excessive options can overwhelm users and lead to decision fatigue.</p>
<p>To address this, developers should simplify interfaces, minimise unnecessary options, and guide users through processes step-by-step rather than presenting everything at once.</p>
<p>Another important cognitive principle discussed is Miller’s Law, which suggests that the average person can hold approximately seven (plus or minus two) items in working memory at a time. This limitation highlights the need to present information in manageable chunks.</p>
<p>By breaking content into smaller groups and avoiding information overload, developers can improve comprehension and usability.</p>
<p>User expectations are strongly shaped by Jakob’s Law, which says that people spend most of their time on other websites and therefore expect similar patterns across digital products.</p>
<p>Instead of reinventing basic interactions, developers should follow familiar conventions such as placing the logo in the top‑left, the shopping cart in the top‑right, and keeping scrolling behaviour predictable.</p>
<p>But innovation is still possible where it truly adds value. As we discussed with the Aesthetic‑Usability Effect, users are far more tolerant of new or unusual design patterns when the interface is visually appealing and thoughtfully crafted.</p>
<p>The Gestalt Principles provided additional insight into how users visually organise information. The principle of proximity suggests that objects placed close together are perceived as related, so grouping related elements improves clarity. Similarity indicates that elements with consistent colours, shapes, or styles are seen as belonging together, reinforcing visual hierarchy and function. Closure explains that users can perceive incomplete shapes as complete, allowing for minimalistic designs where the brain fills in missing details. Continuity highlights that users naturally follow smooth visual paths, meaning layouts should guide the eye logically through alignment and structure.</p>
<p>We also looked at The Von Restorff Effect which emphasizes that elements which stand out are more likely to be remembered. By using contrast in colour, size, or design, important features such as buttons or alerts can capture user attention.</p>
<p>Managing complexity was addressed by Tesler’s Law, which asserts that every system has inherent complexity that cannot be eliminated but only managed.</p>
<p>Developers must therefore shift complexity away from the user by simplifying interfaces while handling intricate processes behind the scenes.</p>
<p>The Zeigarnik Effect reveals that people remember unfinished tasks better than completed ones, creating a sense of mental tension. This can be leveraged by incorporating progress indicators, checklists, and reminders that encourage users to complete tasks.</p>
<p>Similarly, the Peak-End Rule suggests that users judge an experience based on its most intense moment and its conclusion. Developers should create memorable highlights and ensure a smooth, satisfying ending to user journeys.</p>
<p>We also discussed the Goal-Gradient Effect, which explains that users become more motivated as they approach the completion of a task. By showing progress –such as indicating that a process is “80% complete” –&nbsp;and breaking tasks into stages, developers can encourage users to finish what they have started.</p>
<p>In terms of system interaction, Postel’s Law advises developers to be flexible in accepting user input while maintaining strict standards for output. This means allowing different input formats while ensuring consistent and reliable system responses.</p>
<p>Performance is equally important, as highlighted by the Doherty Threshold, which shows that productivity increases when system response times stay under 400 milliseconds. Fast systems keep users engaged and create a sense of ease.</p>
<p>This means that developers should focus on building interfaces that feel instant, even when real processing takes longer, by combining smart engineering practices with thoughtful design patterns that maintain the illusion of speed.</p>
<p>Memory and attention are further explained by the Serial Position Effect, where users tend to remember the first and last items in a sequence more than those in the middle. Developers should position key information or actions at the beginning or end of lists.</p>
<p>Simplicity is reinforced by Occam’s Razor, which argues that the simplest solution is often the most effective. Eliminating unnecessary features reduces friction and enhances usability, and we further discussed about Parkinson’s Law, which suggests that tasks expand to fill the time available, indicating the importance of setting constraints such as deadlines or timers to encourage timely action.</p>
<p>These principles collectively highlight the importance of simplicity, clarity, performance, and user psychology in design. By applying them thoughtfully, developers can create intuitive, efficient, and engaging user experiences that align with both human behaviour and user expectations.</p>
<h2 id="heading-references">References</h2>
<p>Budiu, R. (2022). <em>Fitts’s Law and Its Applications in UX</em>. [online] Nielsen Norman Group. Available at: <a href="https://www.nngroup.com/articles/fitts-law/">https://www.nngroup.com/articles/fitts-law/</a>.</p>
<p>Bustamante, N. (2023). <em>Gestalt Psychology? Definition, Principles, &amp; Examples - Simply Psychology</em>. [online] <a href="http://www.simplypsychology.org">www.simplypsychology.org</a>. Available at: <a href="https://www.simplypsychology.org/what-is-gestalt-psychology.html">https://www.simplypsychology.org/what-is-gestalt-psychology.html</a>.</p>
<p>Cherry, K. (2024). <em>The Zeigarnik Effect Is Why You Keep Thinking of Unfinished Work</em>. [online] Verywell Mind. Available at: <a href="https://www.verywellmind.com/zeigarnik-effect-memory-overview-4175150">https://www.verywellmind.com/zeigarnik-effect-memory-overview-4175150</a>.</p>
<p>DO, A.M., RUPERT, A.V. and WOLFORD, G. (2008). Evaluations of pleasurable experiences: The peak-end rule. <em>Psychonomic Bulletin &amp; Review</em>, 15(1), pp.96–98. doi:<a href="https://doi.org/10.3758/pbr.15.1.96">https://doi.org/10.3758/pbr.15.1.96</a>.</p>
<p>GUPTA, S., GUPTA, S., MAHENDRA, A. and GUPTA, S. (2006). Inverse Halo Nevus. <em>Dermatologic Surgery</em>, 32(6), pp.871–872. doi:<a href="https://doi.org/10.1097/00042728-200606000-00025">https://doi.org/10.1097/00042728-200606000-00025</a>.</p>
<p>‌Hall, D. (2023). <em>Pilot Error, Chapanis and The Shape of Things to Come</em>. [online] UX Magazine. Available at: <a href="https://uxmag.com/articles/pilot-error-chapanis-and-the-shape-of-things-to-come">https://uxmag.com/articles/pilot-error-chapanis-and-the-shape-of-things-to-come</a>.</p>
<p>Hunt, R.R. (1995). The subtlety of distinctiveness: What von Restorff really did. <em>Psychonomic Bulletin &amp; Review</em>, 2(1), pp.105–112. doi:<a href="https://doi.org/10.3758/bf03214414">https://doi.org/10.3758/bf03214414</a>.</p>
<p>Kahneman, D., Fredrickson, B.L., Schreiber, C.A. and Redelmeier, D.A. (1993). When More Pain Is Preferred to Less: Adding a Better End. <em>Psychological Science</em>, 4(6), pp.401–405. doi:<a href="https://doi.org/10.1111/j.1467-9280.1993.tb00589.x">https://doi.org/10.1111/j.1467-9280.1993.tb00589.x</a>.</p>
<p>Mod, D. (2024). <em>Doherty Threshold: UX Law of Swift Interactions</em>. [online] Articles on everything UX: Research, Testing &amp; Design. Available at: <a href="https://blog.uxtweak.com/doherty-threshold/">https://blog.uxtweak.com/doherty-threshold/</a>.</p>
<p>Miller, G.A. (1956). The magical number seven, plus or minus two: Some limits on our capacity for processing information. <em>Psychological Review</em>, [online] 101(2), pp.343–352. doi:<a href="https://doi.org/10.1037/0033-295x.101.2.343">https://doi.org/10.1037/0033-295x.101.2.343</a>.</p>
<p>Proctor, R.W. and Schneider, D.W. (2018). Hick’s law for choice reaction time: A review. <em>Quarterly Journal of Experimental Psychology</em>, [online] 71(6), pp.1281–1299. doi:<a href="https://doi.org/10.1080/17470218.2017.1322622">https://doi.org/10.1080/17470218.2017.1322622</a>.</p>
<p>Yablonski, J. (2022). <em>Hick’s Law</em>. [online] Laws of UX. Available at: <a href="https://lawsofux.com/hicks-law/">https://lawsofux.com/hicks-law/</a>.</p>
<p>Yablonski, J. (2022). <em>Goal-Gradient Effect</em>. [online] Laws of UX. Available at: <a href="https://lawsofux.com/goal-gradient-effect/">https://lawsofux.com/goal-gradient-effect/</a>.</p>
<p>‌</p>
<p>‌</p>
<p>‌</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Automate Form UX Audits: Errors, Hints, and Keyboard Flows ]]>
                </title>
                <description>
                    <![CDATA[ Forms are often the gatekeepers to conversions on a site or application. Abandoned carts, partially signed-up users, and users who stop engaging with your app are often thanks to friction with forms.  ]]>
                </description>
                <link>https://www.freecodecamp.org/news/automate-form-ux-audits-handbook/</link>
                <guid isPermaLink="false">69bc38cfb238fd45a3231433</guid>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                    <category>
                        <![CDATA[ user experience ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UIUX ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ forms ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oleh Romanyuk ]]>
                </dc:creator>
                <pubDate>Thu, 19 Mar 2026 17:56:31 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/5bf2b730-1a9f-46e9-9809-b63926589f00.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Forms are often the gatekeepers to conversions on a site or application. Abandoned carts, partially signed-up users, and users who stop engaging with your app are often thanks to friction with forms.</p>
<p>People will also abandon a site when they don’t understand an error message, can’t navigate through fields easily, or can’t get the help they need right away.</p>
<p>This guide will show you how to create automated systems that detect these issues before your users do. Together, we'll write code that systematically checks your forms so you don’t have to go through each field by hand in the hopes of finding problems.</p>
<p>Here's what we'll build together:</p>
<ul>
<li><p>Scripts that confirm your error messages are helpful and specific rather than generic and annoying.</p>
</li>
<li><p>Automated checks that guarantee the hint text appears in the appropriate location and at the appropriate time.</p>
</li>
<li><p>Tests to ensure keyboard users can navigate your forms without becoming lost or stuck.</p>
</li>
<li><p>A comprehensive audit system that performs these checks automatically and provides you with a list of fixes ranked in order of priority.</p>
</li>
<li><p>Integration with your development process so that each time you make a code change, these checks are performed.</p>
</li>
</ul>
<p>By the end of this handbook, you'll know how to:</p>
<ul>
<li><p>Configure automated audits for any application form.</p>
</li>
<li><p>Verify error messages against accessibility guidelines and usability best practices.</p>
</li>
<li><p>Make sure the hint text aids users rather than confounds them.</p>
</li>
<li><p>Verify that all users can finish your forms by testing the keyboard navigation.</p>
</li>
<li><p>Link audit findings to actual business metrics, such as conversion rates.</p>
</li>
<li><p>As part of your deployment procedure, run these audits automatically.</p>
</li>
</ul>
<p>You can run the functional JavaScript code in each section right away. Because the examples use vanilla JavaScript, they can be used with any framework, including React, Vue, Angular, or simply HTML. Although you don't have to be an expert, you should be able to follow along with JavaScript to get this most out of this guide.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ol>
<li><p><a href="#heading-why-should-you-automate-form-audits-in-the-first-place">Why Should You Automate Form Audits in the First Place?</a></p>
</li>
<li><p><a href="#heading-how-to-define-concise-objectives-and-scope">How to Define Concise Objectives and Scope</a></p>
</li>
<li><p><a href="#heading-how-to-scope-audit-boundaries">How to Scope Audit Boundaries</a></p>
</li>
<li><p><a href="#heading-how-to-incorporate-heuristic-evaluation-and-quantitative-data">How to Incorporate Heuristic Evaluation and Quantitative Data</a></p>
</li>
<li><p><a href="#heading-how-to-define-automated-test-cases-for-form-components">How to Define Automated Test Cases for Form Components</a></p>
</li>
<li><p><a href="#heading-how-to-consistently-confirm-keyboard-navigation-flows">How to Consistently Confirm Keyboard Navigation Flows</a></p>
</li>
<li><p><a href="#heading-aiinformed-navigation-pattern-detection">AI-Informed Navigation Pattern Detection</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-why-should-you-automate-form-audits-in-the-first-place">Why Should You Automate Form Audits in the First Place?</h2>
<p>Manual testing will typically find easy problems. But it may miss the systematic issues with forms across your entire application. You know the type of errors I’m talking about – those that don’t state incorrect values, missing keyboard support for fields, or hints that don’t have a clear place for help based on static design.</p>
<p>Research on user experience design shows that an effective UX can be strategically built, refined, or designed by using continuous feedback loops (Source: <a href="https://www.researchgate.net/publication/382804453_Assessment_of_User_Experience_UX_Design_Trends_in_Mobile_Applications">Okonkwo, Research Gate</a>). Automated audits are a good way of putting this into practice, as they can help you find issues at scale before you release your product.</p>
<p>The key advantage here is coverage. You can prepare form UX audit basics so you and your teammates can check every form field, validation rule, and keyboard interaction in a systematic way.</p>
<h3 id="heading-key-form-components-to-audit"><strong>Key Form Components to Audit</strong></h3>
<p>Before we create our roadmap for the UX audit, let’s talk about the three main elements of forms that typically have issues:</p>
<ul>
<li><p><strong>Error states</strong> indicate what went wrong, as well as how to fix it. The clearer they are, the better: the confusion of generic messages like "Invalid input" frustrates users. In contrast, specific feedback like "Email must contain @ symbol" is specific enough to help them get things completed.</p>
</li>
<li><p><strong>Hint text</strong> helps prevent errors before users can input anything. Proactive guidance like "Password must contain 8+ characters" provides realistic expectations. Placing hint text in the right location and conveying its message at the appropriate time also determines how useful the hint text will be.</p>
</li>
<li><p><strong>Keyboard flows</strong> distinguish accessible forms from broken forms. Tab order, focus order, and keyboard shortcuts dictate whether a user can complete their form without a mouse.</p>
</li>
</ul>
<p>To guide you through the audit workflow for each component, we’ll focus on three user flows: a sign-up form, checkout, and a contact form. All of these affect the conversion rate of a product’s users. And each of these elements maps to multiple metrics you can track.</p>
<p>We’ll use Nielsen Norman Group's 10 usability heuristics (Source: <a href="https://www.nngroup.com/articles/ten-usability-heuristics/">Jakob Nielsen, NNgroup</a>) as a foundation while incorporating any data indicators. These heuristics are:</p>
<ul>
<li><p><strong>System status visibility</strong>: Users should always be aware of what's going on thanks to prompt feedback</p>
</li>
<li><p><strong>System and real-world match</strong>: Use the user's language instead of technical terms</p>
</li>
<li><p><strong>User freedom and control</strong>: Enable users to quickly correct errors</p>
</li>
<li><p><strong>Consistency and standards</strong>: Adhere to platform norms so users don't have to question whether various terms or behaviors have the same meaning.</p>
</li>
<li><p><strong>Error prevention</strong>: Design to stop issues before they start</p>
</li>
<li><p><strong>Recognition rather than recall</strong>: Show options rather than making users memorize details.</p>
</li>
<li><p><strong>Flexibility and efficiency of use</strong>: Provide shortcuts for experienced users while keeping things simple for beginners.</p>
</li>
<li><p><strong>Aesthetic and minimalist design</strong>: Don't clutter interfaces with irrelevant information.</p>
</li>
<li><p><strong>Help users recognize, diagnose, and recover from errors</strong>: Error messages should clearly explain the problem and suggest a solution.</p>
</li>
<li><p><strong>Help and documentation</strong>: Provide easy-to-search help when needed.</p>
</li>
</ul>
<p>For form audits, we'll focus especially on heuristics #5 (error prevention through hint text), #6 (making requirements visible), and #9 (clear error recovery). These directly affect whether users can complete forms successfully.</p>
<p>There’s one more important thing to note before we proceed. For each component, you’ll want to identify what tests you can automate as part of your test case. For each form component, start building checks programmatically for several criteria:</p>
<ul>
<li><p><strong>Accessibility</strong> – for contrast ratios, ARIA labels, and focus indicators.</p>
</li>
<li><p><strong>Performance</strong> – for the time it takes to validate fields and render error messages.</p>
</li>
<li><p><strong>Visual consistency</strong> – for error state styling, hint text patterns, and keyboard focus.</p>
</li>
</ul>
<p>We’ll prioritize fixes with a high impact that will help prevent users from abandoning a form. Also, each audit will produce actionable information along with a line of code, acceptance criteria, and example code for fixes.</p>
<p>Now, let’s start building our form UX audit workflow.</p>
<h2 id="heading-how-to-define-concise-objectives-and-scope">How to Define Concise Objectives and Scope</h2>
<p>Before you even put your fingers to the keyboard, you'll want to determine what exactly you’re measuring and for what purpose. There’s a golden rule: ambiguous statements will yield ambiguous results. Having specific objectives linked to user behavior and business metrics is what creates actionable audits.</p>
<h3 id="heading-identifying-form-types-and-objectives">Identifying Form Types and Objectives</h3>
<p>First, you need to know what form you’re going to audit. Let’s start by mapping the three forms that have the greatest direct impact on the success of your application and defining the nuances and objectives of each one.</p>
<h4 id="heading-1-a-signup-forms-key-goal-is-user-acquisition">1. A signup form’s key goal is user acquisition.</h4>
<p>Every friction point - like poorly defined password requirements, vague expectations for email formats, and a lack of field labels - means a user will likely abandon the signup process. Your audit must identify these user flows.</p>
<h4 id="heading-2-checkout-forms-are-aimed-at-bringing-revenue">2. Checkout forms are aimed at bringing revenue</h4>
<p>User engagement improves significantly when applications use user-centered design principles – shocking, right? (Source: <a href="https://www.researchgate.net/publication/382804453_Assessment_of_User_Experience_UX_Design_Trends_in_Mobile_Applications">Okonkwo, ResearchGate</a>). In checkout flows, this means that error messages appear inline, hints show requirements before a user can type, and keyboard navigation follows the expected tab order from shipping to payment fields.</p>
<h4 id="heading-3-contact-forms-have-the-objective-of-establishing-communication">3. Contact forms have the objective of establishing communication</h4>
<p>Often, devs pay less attention to contact forms than to transactional forms. But contact forms are crucial for proposal requests, customer support requests, collaboration requests, and so on. A broken contact form can mean lost business.</p>
<p>Now that you’ve identified the type of form and its key objective, let’s do something equally important: link these high-level objectives to specific, measurable metrics.</p>
<h3 id="heading-connecting-objectives-and-metrics-to-track">Connecting Objectives and Metrics to Track</h3>
<p>Every objective for the audit maps to a set of measurements. Here’s how to build this continuum:</p>
<h4 id="heading-error-message-metrics">Error message metrics</h4>
<p>Your audit should evaluate whether error messages fulfill three criteria:</p>
<ol>
<li><p>Specificity (Does the message indicate what the problem is?),</p>
</li>
<li><p>Timing (In what context will the user see the error?), and</p>
</li>
<li><p>Actionable (Does the message explain what the user should do to recover?).</p>
</li>
</ol>
<p>For example, "password too weak" does not provide actionable information and isn’t specific enough, while "Password must have at least one uppercase character, one number, and one special character" is highly actionable and provides clear information on what the user needs to do.</p>
<p><strong>You can measure this by tracking two things:</strong> what percentage of your error messages mention the specific field name, and how many errors show up immediately when users leave a field versus only appearing after they hit submit.</p>
<h4 id="heading-hints-can-reduce-user-errors-before-they-occur-your-audit-should-validate">Hints can reduce user errors before they occur. Your audit should validate:</h4>
<ul>
<li><p>Whether a hint’s positioning is proactive (for instance, is the hint text located before users engage the provided input field?).</p>
</li>
<li><p>Visual proximity (Is the hint text next to the input field?).</p>
</li>
<li><p>Accessibility (for example, are the hints connected to the fields programmatically using aria-describedby?)</p>
</li>
</ul>
<p>The latter is especially important, as screen readers require explicit connections to announce hints at the correct time. You’ll want to measure these using metrics like the time to display a hint (immediate vs delayed) and the number of ARIA-associated hint elements.</p>
<h4 id="heading-keyboard-flow-metrics-are-also-directly-connected-to-accessibility">Keyboard flow metrics are also directly connected to accessibility</h4>
<p>Your audit should define if there is a correct order logic. Do fields follow the visual layout? When the tabindex jumps around sporadically across the screen, users lose context.</p>
<p>It should also determine if the focus visibility is the current field and if that’s clearly indicated. When the focus is invisible or subtle, you end up making your users guess where they are.</p>
<p>Keyboard shortcuts let users submit forms, clear fields, or jump between sections without touching their mouse. Everyone benefits from this, not just people using screen readers or other assistive technology.</p>
<p>You will want to measure these with the tabindex sequence alignment to the visual layout, focus indicator contrast ratios, and by defining if there are keyboard shortcuts for submitting, clearing, and moving about the forms.</p>
<p>Now that you have outlined the key metrics and principles applicable to the form you’re auditing, it’s time to define the specific area you want to focus on.</p>
<h2 id="heading-how-to-scope-audit-boundaries">How to Scope Audit Boundaries</h2>
<p>You’ll need to define exactly what forms and fields your audit will cover. You’ll want to start small in order to build working automations and then slowly expand.</p>
<h3 id="heading-setting-the-initial-scope">Setting the Initial Scope</h3>
<p>You should start with forms in your application’s critical user paths. We’ll use the below JavaScript snippet as an example. Paste this configuration object into your audit automation tool or script:</p>
<pre><code class="language-python">const auditScope = {
  signupForm: {
    url: '/signup',
    fields: ['email', 'password', 'confirmPassword'],
    priority: 'critical'
  },
  checkoutForm: {
    url: '/checkout',
    fields: ['cardNumber', 'expiryDate', 'cvv', 'billingZip'],
    priority: 'critical'
  },
  contactForm: {
    url: '/contact',
    fields: ['name', 'email', 'subject', 'message'],
    priority: 'high'
  }
};
</code></pre>
<p>In the code above, the auditScope object lists critical forms (signup, checkout, and contact forms), specifies their URLs along with important fields to check (such as email, password, cardNumber), and lists their priority level. This helps the auditing system see what resources to prioritize.</p>
<p>The priority property allows your audit system to prioritize high-impact forms first when protocol limits the resources available. Such a method prevents your system from being overwhelmed with too broad a scope.</p>
<h3 id="heading-setting-the-audit-execution-plan">Setting the Audit Execution Plan</h3>
<p>Your objectives dictate how the audit system will act. After you have defined the scope, you can divide the workflow into several definite phases.</p>
<ul>
<li><p><strong>Phase 1:</strong> Static analysis will address the structure of the HTML document and verify the ARIA attributes, tab indices, and markup patterns for semantic use. This can discover structural issues that require no user interaction.</p>
</li>
<li><p><strong>Phase 2:</strong> Dynamic testing simulates user interactions to identify the occurrence of errors, when hints are displayed, and when a keyboard user would navigate to which elements. This can identify runtime problems that were not revealed through static analysis.</p>
</li>
<li><p><strong>Phase 3:</strong> Visual verification measures spacing, contrast ratios, or positioning of elements, but using visually computed styles. This allows us to examine the visual design in relation to meeting either UX or UI objectives.</p>
</li>
</ul>
<p>Each phase will result in findings that continually tie back to your defined objectives. In the case of a failed check, the audit report will show which objective contributed to the finding, the current state of the component, the target states, and recommendations for the solution.</p>
<h3 id="heading-field-level-objectives">Field-level objectives</h3>
<p>For each field, you should tell the script or the automated tool what the audit is actually checking. Each check is a specific automated test. When the audit is executed, every check is confirmed for every field, and failures are noted.</p>
<p>For instance, in the following snippet, for each field we provide (like "email" or "password"), we list three categories of checks: errorChecks, hintChecks, and keyboardChecks. When you link this object to your audit automation system (for example, UI testing frameworks, accessibility checkers), your audit automation system runs all these tests on every field. It will report any test failures so you can see which part of the input is broken or missing.</p>
<pre><code class="language-python">const fieldObjectives = {
  email: {
    errorChecks: [
      'hasInlineValidation',
      'errorMessageSpecific',
      'showsValidFormatExample'
    ],
    hintChecks: [
      'hintVisibleBeforeInteraction',
      'hintExplainsFormat',
      'hintAccessible'
    ],
    keyboardChecks: [
      'tabOrderCorrect',
      'focusVisible',
      'supportsAutocomplete'
    ]
  },
  password: {
    errorChecks: [
      'hasInlineValidation',
      'listsAllRequirements',
      'showsProgressIndicator'
    ],
    hintChecks: [
      'hintListsRequirements',
      'hintVisibleBeforeTyping',
      'hintPersistsDuringTyping'
    ],
    keyboardChecks: [
      'tabOrderCorrect',
      'focusVisible',
      'supportsPasswordManagers'
    ]
  }
};
</code></pre>
<p>This leads to a very granular, consistent, and repeatable test of important user input components so you can validate usability, accessibility, and correctness of the form.</p>
<h3 id="heading-linking-objectives-to-business-kpis">Linking Objectives to Business KPIs</h3>
<p>The findings of the audit should link back to business impact. Let’s look at how our objectives map to key performance indicators.</p>
<p>The impact on conversion rate should be direct and specific. For instance, improved error messages directly impact the form completion rate:</p>
<ul>
<li><p><strong>Baseline</strong>. The current abandonment rate for forms.</p>
</li>
<li><p><strong>Target</strong>. Decrease abandonment by 15% due to clear error messages.</p>
</li>
<li><p><strong>Audit validation.</strong> 100% of error messages are clear and specific.</p>
</li>
</ul>
<p>Reducing support tickets is another priority. In this case, better hint text provides less confusion:</p>
<ul>
<li><p><strong>Baseline</strong>. Volume of support requests related to forms currently.</p>
</li>
<li><p><strong>Target</strong>. Decrease the number of support tickets by 25%.</p>
</li>
<li><p><strong>Audit validation.</strong> 100% of complex fields have proactive hints.</p>
</li>
</ul>
<p>Accessibility compliance is another important goal. Keyboard navigation has a direct impact on the legal compliance and reach of a wider base of users. The example of the KPIs here can be the following:</p>
<ul>
<li><p><strong>Baseline</strong>. Current level of WCAG conformance.</p>
</li>
<li><p><strong>Target</strong>. All forms to be WCAG 2.1 AA compliant.</p>
</li>
<li><p><strong>Audit validation.</strong> 100% of fields work with a keyboard only.</p>
</li>
</ul>
<p>After you create such measurable criteria for success, you should actually give them as thresholds to your system. Here’s an example of how you can provide defined measures for passing and failing for the automated audit:</p>
<pre><code class="language-python">const auditThresholds = {
  errorMessages: {
    specificityScore: 0.9,  // 90% must include field-specific details
    inlineValidationPercentage: 1.0,  // 100% must show inline errors
    actionabilityScore: 0.85  // 85% must include fix instructions
  },
  hintText: {
    proactiveDisplayPercentage: 1.0,  // 100% must appear before interaction
    proximityMaxPixels: 8,  // Hints must be within 8px of fields
    ariaAssociationPercentage: 1.0  // 100% must have aria-describedby
  },
  keyboardFlow: {
    tabOrderCorrectnessScore: 1.0,  // 100% must follow visual layout
    focusContrastRatio: 3.0,  // Minimum 3:1 contrast for focus indicators
    shortcutCoveragePercentage: 0.8  // 80% of actions must have shortcuts
  }
};
</code></pre>
<p>As you can see, under errorMessages, the specificityScore of 0.9 states that 90% of error messages must include details specific to each field. Also, within the hintText directions, the proactiveDisplayPercentage of 1.0 demands that the hints appear before the user starts typing, not after, for the test to be passed.</p>
<h3 id="heading-the-5cs-framework-for-audit-documentation">The 5Cs Framework for Audit Documentation</h3>
<p>When you document your audit results, use the 5Cs framework to make sure your reports are actually useful:</p>
<ul>
<li><p><strong>Coverage</strong>: Which forms and fields did you test? Be specific about the scope.</p>
</li>
<li><p><strong>Completion</strong>: Did you run all the planned checks? Note any that were skipped and why.</p>
</li>
<li><p><strong>Consistency</strong>: Do your results use the same format and terminology throughout? This makes reports easier to scan.</p>
</li>
<li><p><strong>Clarity</strong>: Can a developer read the failure report and know exactly what to fix? Include the current state, expected state, and code examples.</p>
</li>
<li><p><strong>Correctness</strong>: Are your checks testing the right things? Validate that failures match real user problems, not just technical violations.</p>
</li>
</ul>
<p>This framework helps both designers and developers understand audit results and take action quickly.</p>
<h2 id="heading-how-to-incorporate-heuristic-evaluation-and-quantitative-data">How to Incorporate Heuristic Evaluation and Quantitative Data</h2>
<p>Once you've established objectives, you’ll want to base your audit on the usability principles and behavior patterns of users. This combination of established usability heuristics along with quantitative data can help you verify that your automated checks are surfacing issues that users actually experience – and not fictional edge cases (Source: <a href="https://www.nngroup.com/articles/ten-usability-heuristics/">Jakob Nielsen, NNgroup</a>).</p>
<p>The best way to do this is to map the issues to the common standard of the Web Content Accessibility Guidelines and use that as the basis for your audit (Source: <a href="https://www.w3.org/TR/WCAG21/">WCAG 2.1, W3C Recommendation</a>). For every identified problem, identify the WCAG success criteria that the issue violates. This will give you clear requirements that you can use as an automated check and that should be commonly understood by everyone working on the audits.</p>
<p>In the automated script, you can use the following code to map these guidelines:</p>
<pre><code class="language-python">const wcagMapping = {
  errorIdentification: {
    criterion: '3.3.1',
    level: 'A',
    requirement: 'Error messages must identify the item in error',
    testFunction: 'checkErrorIdentification'
  },
  errorSuggestion: {
    criterion: '3.3.3',
    level: 'AA',
    requirement: 'Error messages must provide suggestions for correction',
    testFunction: 'checkErrorSuggestions'
  },
  labelInName: {
    criterion: '2.5.3',
    level: 'A',
    requirement: 'Accessible name must contain visible label text',
    testFunction: 'checkLabelInName'
  },
  focusOrder: {
    criterion: '2.4.3',
    level: 'A',
    requirement: 'Focus order must preserve meaning and operability',
    testFunction: 'checkFocusOrder'
  }
};
</code></pre>
<p>If any part of the form violates WCAG 3.3.1 – perhaps it doesn’t identify the field when it provides an error – your audit report can document it as follows:</p>
<p>"The error message displayed on the email field said 'Invalid input' but didn’t identify the requirement it didn't meet. WCAG 3.3.1 states that the error must identify the field with the error (potential fix: 'Email must have an @ symbol'). 3.3.1 is the mapped criteria."</p>
<p>Nielsen's heuristics tell you what good usability looks like. But tools like Google Analytics and Hotjar show you what users actually do on your forms. When you combine both – usability principles and real user behavior data – you make better decisions about which problems to fix first.</p>
<p>Research shows this combined approach catches more real issues than either method alone (Sources: <a href="https://www.researchgate.net/publication/334385231_User_Experience_Evaluation_Using_Mouse_Tracking_and_Artificial_Intelligence">Souza and others, IEEE Access</a>). Use both types of data to prioritize what your automated audits should check.</p>
<h3 id="heading-define-binary-passfail-criteria">Define Binary Pass/Fail Criteria</h3>
<p>Automation requires clear results. Your audit must document whether a component passed or failed its WCAG criteria. The process must yield binary results – yes/no, positive/negative.</p>
<p>For instance, the following code incorporates a definite, binary audit check to verify whether a form field is compliant with WCAG 3.3.1 criteria for error identification (Source: <a href="https://www.w3.org/TR/WCAG21/">WCAG 2.1, W3C Recommendation</a>):</p>
<pre><code class="language-python">function checkErrorIdentification(field) {
  const errorElement = field.querySelector('[role="alert"], .error-message');
  
  if (!errorElement) {
    return {
      pass: false,
      wcag: '3.3.1',
      severity: 'critical',
      message: `Field "${field.name}" lacks error message element`,
      fix: 'Add aria-describedby pointing to error container'
    };
  }
  
  const errorText = errorElement.textContent.trim();
  const hasFieldReference = errorText.toLowerCase().includes(field.name.toLowerCase()) 
    || errorText.toLowerCase().includes(field.labels[0]?.textContent.toLowerCase());
  
  if (!hasFieldReference) {
    return {
      pass: false,
      wcag: '3.3.1',
      severity: 'major',
      message: `Error message "${errorText}" doesn't identify field`,
      fix: `Include field name in error: "\({field.labels[0]?.textContent} \){errorText}"`
    };
  }
  
  return { pass: true, wcag: '3.3.1' };
}
</code></pre>
<p>The error message identified the error, and each component definitively passes or fails the criterion. There’s no room for interpretation or doubt.</p>
<h3 id="heading-standardize-error-messages-and-hint-messages">Standardize Error Messages and Hint Messages</h3>
<p>Keep in mind that automated functions require familiarity and consistency. You can create centralized repositories with libraries of accepted usage patterns and approval that developers can refer to, and your tests can check that your forms are using standardized messages.</p>
<p>For example, in the following snippet, the errorLibrary object provides a single source of truth for every acceptable error message your application will display for specific fields. For each field, there are appropriately defined message strings for common validation issues (like empty, invalid, duplicate). Similarly, the hintLibrary object provides a single source of truth for every hint text that prefaces user input.</p>
<pre><code class="language-python">const errorLibrary = {
  email: {
    empty: 'Email address is required',
    invalid: 'Email must include @ symbol and domain (example: user@domain.com)',
    duplicate: 'This email is already registered. Try signing in instead.'
  },
  password: {
    empty: 'Password is required',
    tooShort: 'Password must be at least 8 characters',
    missingUppercase: 'Password must include at least one uppercase letter',
    missingNumber: 'Password must include at least one number',
    missingSpecial: 'Password must include at least one special character (!@#$%^&amp;*)'
  }
};

const hintLibrary = {
  email: 'Enter your email address (example: name@company.com)',
  password: 'Create a password with 8+ characters, including uppercase, number, and special character',
  phone: 'Enter 10-digit phone number without dashes (example: 5551234567)'
};
</code></pre>
<p>By having a single source of these patterns, you won’t run the risk of writing duplicate or misaligned messages in different areas across the app, increasing maintainability.</p>
<h3 id="heading-utilize-definite-aria-identifiers">Utilize Definite ARIA Identifiers</h3>
<p>If you use consistent ARIA attributes, you can automate checks. As an example, in the following snippet, we explicitly define which ARIA attributes connect error messages, hints, and fields. The auditARIAImplementation function checks whether each field has an accessible label (either an HTML element or an aria-label attribute) to meet WCAG 1.3.1. Without it, users will likely find it hard to identify the purpose of the input.</p>
<pre><code class="language-python">function auditARIAImplementation(field) {
  const checks = {
    hasLabel: !!field.labels?.length || !!field.getAttribute('aria-label'),
    hasDescription: !!field.getAttribute('aria-describedby'),
    hasErrorMessage: !!field.getAttribute('aria-errormessage'),
    hasRequired: field.hasAttribute('required') || field.getAttribute('aria-required') === 'true'
  };
  
  const failures = [];
  
  if (!checks.hasLabel) {
    failures.push({
      wcag: '1.3.1',
      message: `Field "${field.name}" lacks accessible label`,
      fix: 'Add &lt;label&gt; element or aria-label attribute'
    });
  }
  
  if (!checks.hasDescription) {
    failures.push({
      wcag: '3.3.2',
      message: `Field "${field.name}" lacks hint text association`,
      fix: 'Add aria-describedby pointing to hint element ID'
    });
  }
  
  if (field.dataset.validatable &amp;&amp; !checks.hasErrorMessage) {
    failures.push({
      wcag: '3.3.1',
      message: `Validatable field "${field.name}" lacks aria-errormessage`,
      fix: 'Add aria-errormessage attribute pointing to error container ID'
    });
  }
  
  return {
    pass: failures.length === 0,
    failures
  };
}
</code></pre>
<p>This function checks for specific ARIA-tied patterns that your design system prescribes. The great thing is that you can check the code in CI/CD pipelines to maintain implementation standards.</p>
<p>The next section will help you identify specific automated test cases for errors, hints, and keyboard flows.</p>
<h2 id="heading-how-to-define-automated-test-cases-for-form-components">How to Define Automated Test Cases for Form Components</h2>
<p>Now that you've established a baseline with WCAG standards, heuristics, and user data, you can create specific automated test cases. Each test case targets a measurable quality for the error messages, hint text, or keyboard navigation functionality of each form component. The following sections will provide concrete ways to automate these checks for each form component.</p>
<h3 id="heading-automated-error-message-checks">Automated Error Message Checks</h3>
<p>Error messages are crucial conversion points. Your automated checks should ensure that each error message meets the specificity, timing, and actionability criteria. Every error message must convey what exactly has gone wrong. Generic error messages don’t pass this quality check.</p>
<p>For automation, your checks can provide insight as to whether the error message references the specific construction of the field. For instance, in the following snippet, the method verifies that every error message that appears in a form serves to pinpoint the input problem, not use a vague general expression.</p>
<pre><code class="language-python">function auditErrorSpecificity(formId) {
  const form = document.getElementById(formId);
  const fields = form.querySelectorAll('input, textarea, select');
  const failures = [];
  
  fields.forEach(field =&gt; {
    const errorElement = document.querySelector(`[aria-describedby="${field.id}-error"]`);
    if (errorElement) {
      const errorText = errorElement.textContent.toLowerCase();
      const genericTerms = ['invalid', 'error', 'wrong', 'incorrect'];
      const isGeneric = genericTerms.some(term =&gt; 
        errorText.includes(term) &amp;&amp; errorText.split(' ').length &lt; 4
      );
      
      if (isGeneric) {
        failures.push({
          field: field.id,
          message: errorText,
          issue: 'Generic error message lacks specificity',
          wcag: '3.3.1 Error Identification'
        });
      }
    }
  });
  
  return failures;
}
</code></pre>
<p>It looks through field-specific error messages and flags any that use common generic terms in a short, vague message, as ambiguous messages don’t serve the purposes of WCAG 3.3.1 since they don’t provide an actionable correction for user input (Source: <a href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-identified.html">WCAG 3.3.1, WC3</a>).</p>
<h3 id="heading-validation-timing-of-inline-messages">Validation Timing of Inline Messages</h3>
<p>Error messages should show the message when the user leaves the field and not just at submission. Research demonstrates that even just the timing of the feedback alone significantly disrupts user performance. Your automation should check whether errors are displayed inline (Source: <a href="https://www.researchgate.net/publication/282715275_Soft_Keyboard_UX_Evaluation_An_Eye_Tracking_Study">Al-Khalifa and others, ResearchGate</a>).</p>
<p>This code verifies that error messages appear immediately when a user leaves a required input field on blur, as opposed to only showing errors after submitting the entire form.</p>
<pre><code class="language-python">function auditErrorTiming(formId) {
  const form = document.getElementById(formId);
  const fields = form.querySelectorAll('input[required], textarea[required]');
  const failures = [];
  
  fields.forEach(field =&gt; {
    let hasBlurValidation = false;
    let hasInputValidation = false;
    
    // Check for blur event listeners
    const blurListeners = getEventListeners(field).blur || [];
    hasBlurValidation = blurListeners.length &gt; 0;
    
    // Check for input event listeners
    const inputListeners = getEventListeners(field).input || [];
    hasInputValidation = inputListeners.length &gt; 0;
    
    if (!hasBlurValidation &amp;&amp; !hasInputValidation) {
      failures.push({
        field: field.id,
        issue: 'No inline validation detected',
        recommendation: 'Add blur or input event validation',
        wcag: '3.3.1 Error Identification'
      });
    }
  });
  
  return failures;
}
</code></pre>
<p>This audit verifies that an event handler which runs against an inline validator is in place for blur and input events on input fields. It also checks that it flags any that fail to have these interactions as a failure under the WCAG 3.3.1 Error Identification guideline (Source: <a href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-identified.html">WCAG 3.3.1, WC3</a>).</p>
<h3 id="heading-confirm-actionable-recovery-guidance">Confirm Actionable Recovery Guidance</h3>
<p>Error messages must clarify how to recover from any faults or issues. "Password too weak" fails the user. In contrast, the error message "Password must be 8+ characters, contain at least 1 upper case letter, and one numeric character" gives the user enough information to make the proper adjustment.</p>
<p>Let’s take an example of some code that audits password fields to ensure that the error message includes specific actionable recovery instructions outlining character types or character length and clearly guides users on how to correct input errors (Source: <a href="https://www.w3.org/WAI/WCAG21/Understanding/error-suggestion.html">WCAG 3.3.3, WC3</a>).</p>
<pre><code class="language-python">function auditErrorActionability(formId) {
  const form = document.getElementById(formId);
  const failures = [];
  const passwordFields = form.querySelectorAll('input[type="password"]');
  
  passwordFields.forEach(field =&gt; {
    const errorElement = document.getElementById(`${field.id}-error`);
    if (errorElement) {
      const errorText = errorElement.textContent;
      const hasSpecificRequirements = /\d+/.test(errorText) || 
        /uppercase|lowercase|special|character|digit/.test(errorText.toLowerCase());
      
      if (!hasSpecificRequirements) {
        failures.push({
          field: field.id,
          message: errorText,
          issue: 'Error lacks specific recovery guidance',
          wcag: '3.3.3 Error Suggestion'
        });
      }
    }
  });
  
  return failures;
}
</code></pre>
<p>If the error message doesn’t contain these characters or meet the length requirement, the function will flag the instance as a failure with a corresponding WCAG reference.</p>
<h3 id="heading-automated-rich-hint-text-auditing">Automated Rich Hint Text Auditing</h3>
<p>Rich text hints help prevent errors (and hopefully the need for an error message). Research suggests that users who are given proactive guidance improve form completion by up to 23% (Source: <a href="https://www.researchgate.net/publication/382804453_Assessment_of_User_Experience_UX_Design_Trends_in_Mobile_Applications">Okonkwo, ResearchGate</a>). Your automation should confirm that the right hints appear at the right time, in the right places, with appropriate accessible information and presentation.</p>
<p>This function audits form fields to ensure that hint text is seen before the user interacts with the form, helping avoid user errors while filling out the form.</p>
<pre><code class="language-python">function auditHintTiming(formId) {
  const form = document.getElementById(formId);
  const complexFields = form.querySelectorAll('input[type="password"], input[pattern]');
  const failures = [];
  
  complexFields.forEach(field =&gt; {
    const hintElement = document.querySelector(`[id="${field.getAttribute('aria-describedby')}"]`);
    
    if (!hintElement) {
      failures.push({
        field: field.id,
        issue: 'Complex field missing proactive hint text',
        wcag: '3.3.2 Labels or Instructions'
      });
    } else {
      // Check if hint is visible before interaction
      const computedStyle = window.getComputedStyle(hintElement);
      const isVisible = computedStyle.display !== 'none' &amp;&amp; 
        computedStyle.visibility !== 'hidden';
      
      if (!isVisible) {
        failures.push({
          field: field.id,
          issue: 'Hint text hidden until interaction',
          wcag: '3.3.2 Labels or Instructions'
        });
      }
    }
  });
  
  return failures;
}
</code></pre>
<p>If the hint doesn't exist or doesn’t show until after the user interacts with the form, the function will flag it as a failure to satisfy WCAG 3.3.2 Labels or Instructions for a generally consistent and user-friendly form design (Source: <a href="https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions.html">WCAG 3.3.3, WC3</a>).</p>
<h2 id="heading-how-to-consistently-confirm-keyboard-navigation-flows">How to Consistently Confirm Keyboard Navigation Flows</h2>
<p>Keyboard accessibility is required for WCAG compliance, and you can automate most of the testing with code. When people can't use your forms with just a keyboard, they often give up and leave. This directly hurts your conversion rates.</p>
<p>When you document how keyboard navigation should work, you can write automated tests to check if it actually works that way.</p>
<h3 id="heading-outlining-the-interactions">Outlining the Interactions</h3>
<p>Your audit should document expected keyboard interactions for each component. If there's a modal dialog, note that Tab will cycle through the elements within the modal, Escape closes the modal, and the focus returns to the element that opened the modal.</p>
<p>For forms, note that Tab advances through the fields in visual order, Shift+Tab will go back, and Enter will submit the form from the submit button only.</p>
<p>You should document these flows in a data-driven way. A structured format with columns for "Component," "Keystroke," "Expected Action," and "Relevant WCAG" will make both human review and automated parsing much easier:</p>
<pre><code class="language-python">const keyboardPatterns = {
  'modal-dialog': {
    tab: 'Focus next element within modal',
    shiftTab: 'Focus previous element within modal',
    escape: 'Close modal and return focus',
    wcag: '2.1.1 Keyboard, 2.4.3 Focus Order'
  },
  'form-field': {
    tab: 'Move to next field in visual order',
    shiftTab: 'Move to previous field',
    enter: 'Submit only from submit button',
    wcag: '2.1.1 Keyboard, 2.4.3 Focus Order'
  },
  'dropdown-select': {
    space: 'Open dropdown menu',
    arrowDown: 'Navigate to next option',
    arrowUp: 'Navigate to previous option',
    enter: 'Select current option',
    escape: 'Close dropdown without selection',
    wcag: '2.1.1 Keyboard, 4.1.2 Name, Role, Value'
  }
};
</code></pre>
<p>This code aligns these patterns with WCAG guidelines 2.1.1 (Keyboard Accessibility), 2.4.3 (Focus Order), and 4.1.2 (Name, Role, Value) to support users who rely on keyboard inputs (Source: <a href="https://www.w3.org/WAI/WCAG21/Understanding/">WCAG Understanding Docs, WC3</a>).</p>
<h3 id="heading-automated-tab-order-validation">Automated Tab Order Validation</h3>
<p>Tab order should follow the visual layout of the page. When focus jumps around randomly, users get lost. The code below checks that focus moves through fields in the order people expect – top to bottom, left to right. It catches cases where focus skips around even when the tabindex values look correct.</p>
<pre><code class="language-python">function auditTabOrder(formId) {
  const form = document.getElementById(formId);
  const focusableElements = form.querySelectorAll(
    'input, select, textarea, button, a[href], [tabindex]:not([tabindex="-1"])'
  );
  const failures = [];
  
  const elements = Array.from(focusableElements).map(el =&gt; ({
    element: el,
    position: el.getBoundingClientRect(),
    tabindex: parseInt(el.getAttribute('tabindex')) || 0
  }));
  
  for (let i = 1; i &lt; elements.length; i++) {
    const prev = elements[i - 1];
    const curr = elements[i];
    
    // Check if tab order follows visual top-to-bottom, left-to-right
    const visuallyBefore = prev.position.top &lt; curr.position.top || 
      (prev.position.top === curr.position.top &amp;&amp; prev.position.left &lt; curr.position.left);
    
    if (!visuallyBefore &amp;&amp; prev.tabindex === curr.tabindex) {
      failures.push({
        field: curr.element.id,
        issue: 'Tab order does not match visual layout',
        wcag: '2.4.3 Focus Order'
      });
    }
  }
  
  return failures;
}
</code></pre>
<p>In essence, the audit identifies failures to adhere to WCAG 2.4.3 Focus Order while preserving context and the ability to interact with keyboard users as they interact with form fields (Source: <a href="https://www.w3.org/WAI/WCAG21/Understanding/focus-order.html">WCAG 2.4.3, WC3</a>).</p>
<h3 id="heading-verify-focus-visibility">Verify Focus Visibility</h3>
<p>Focus indicators need to be clearly identifiable. According to research, visible focus indicators improved typing and reduced errors significantly (Source: <a href="https://www.researchgate.net/publication/392950031_Enhancing_User_Experience_of_Virtual_Keyboard_Through_Collaborative_and_Speed-Adaptive_Auditory-Vibrotactile_Feedback">Liu and others, ResearchGate</a>).</p>
<p>For instance, focus styles can include an outline, border, or shadow, but they must have enough contrast against the background (at least 3:1) to satisfy WCAG 2.4.7 Focus Visible and 1.4.11 Non-text Contrast (Source: <a href="https://www.w3.org/WAI/WCAG21/Understanding/">WCAG Understanding Docs, WC3</a>). Consider the following example:</p>
<pre><code class="language-python">function auditFocusVisibility(formId) {
  const form = document.getElementById(formId);
  const focusableElements = form.querySelectorAll('input, select, textarea, button');
  const failures = [];
  
  focusableElements.forEach(element =&gt; {
    element.focus();
    const computedStyle = window.getComputedStyle(element);
    
    // Check for visible focus indicator
    const hasOutline = computedStyle.outline !== 'none' &amp;&amp; 
      computedStyle.outlineWidth !== '0px';
    const hasBorder = computedStyle.borderStyle !== 'none';
    const hasBoxShadow = computedStyle.boxShadow !== 'none';
    
    // Check contrast ratio for focus indicator
    const outlineColor = computedStyle.outlineColor;
    const backgroundColor = computedStyle.backgroundColor;
    const contrastRatio = calculateContrastRatio(outlineColor, backgroundColor);
    
    if (!hasOutline &amp;&amp; !hasBorder &amp;&amp; !hasBoxShadow) {
      failures.push({
        field: element.id,
        issue: 'No visible focus indicator',
        wcag: '2.4.7 Focus Visible'
      });
    } else if (contrastRatio &lt; 3) {
      failures.push({
        field: element.id,
        contrastRatio: contrastRatio.toFixed(2),
        issue: 'Focus indicator contrast ratio below 3:1',
        wcag: '1.4.11 Non-text Contrast'
      });
    }
  });
  
  return failures;
}
</code></pre>
<p>Good focus styling helps keyboard users see where they are on the page. This code checks that focus indicators are visible and have enough contrast against the background so users can tell which field they're currently in.</p>
<h3 id="heading-using-automated-testing-tools">Using Automated Testing Tools</h3>
<p>To speed up and automate audits even more efficiently, you can use tools such as <a href="https://developer.chrome.com/docs/lighthouse/overview">Google Lighthouse</a>, <a href="https://chromewebstore.google.com/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd">axe-core</a>, and <a href="https://www.cypress.io/">Cypress</a>. You can also combine these tools to be even more powerful – for example, using axe-core in conjunction with Cypress is the most comprehensive test suite I can suggest.</p>
<p>Here is a workflow you can follow:</p>
<pre><code class="language-python">async function runAccessibilityAudit(formId) {
  const form = document.getElementById(formId);
  const results = await axe.run(form, {
    rules: {
      'label': { enabled: true },
      'aria-required-attr': { enabled: true },
      'aria-valid-attr-value': { enabled: true },
      'keyboard-navigation': { enabled: true },
      'focus-order-semantics': { enabled: true }
    }
  });
  
  const violations = results.violations.map(violation =&gt; ({
    rule: violation.id,
    impact: violation.impact,
    description: violation.description,
    wcag: violation.tags.filter(tag =&gt; tag.startsWith('wcag')),
    elements: violation.nodes.map(node =&gt; node.target)
  }));
  
  return violations;
}
</code></pre>
<p>When you document keyboard patterns and automate the checks, you make sure everyone can complete your forms – whether they use a mouse, keyboard, or screen reader. Run these checks in your CI/CD pipeline to catch problems before they go live.</p>
<h2 id="heading-ai-informed-navigation-pattern-detection">AI-Informed Navigation Pattern Detection</h2>
<p>Machine learning models can help identify strange keyboard navigation sequences that signal potential usability challenges. Combining mouse tracking with artificial intelligence can give you insights into user behavior that aren't possible using traditional strategies (Sources: <a href="https://www.researchgate.net/publication/334385231_User_Experience_Evaluation_Using_Mouse_Tracking_and_Artificial_Intelligence">Souza and others, IEEE Access</a>).</p>
<p>The logic could similarly be applied to keyboard navigation studies, as AI models can be trained on typical successful navigation patterns to signal when users are struggling in their keyboard flows.</p>
<h3 id="heading-pattern-detection-for-navigation-using-ai">Pattern Detection for Navigation Using AI</h3>
<p>AI tools can assess keyboard navigation to find non-compliant actions during testing. For instance, through machine learning, the code sample below captures, evaluates, and categorizes unusual or problematic keyboard navigation behavior on web forms and detects unique keyboard navigation or k-action sequences that are likely indicative of usability concerns.</p>
<pre><code class="language-python">async function detectNavigationAnomalies(formId) {
  const navigationData = captureKeyboardSequence(formId);
  const features = extractNavigationFeatures(navigationData);
  
  // Use machine learning to classify navigation patterns
  const model = await loadTrainedModel('keyboard-anomaly-detection');
  const predictions = await model.predict(features);
  
  const anomalies = predictions.filter(p =&gt; p.confidence &gt; 0.8).map(p =&gt; ({
    sequence: p.keystrokes,
    anomalyType: p.classification,
    severity: p.confidence,
    recommendation: generateRecommendation(p.classification)
  }));
  
  return anomalies;
}

function extractNavigationFeatures(data) {
  return {
    tabSequenceLength: data.tabs.length,
    backtrackCount: countBacktracks(data.tabs),
    focusTrapIndicators: detectFocusTraps(data),
    averageTimePerElement: calculateAverageTime(data),
    sequenceDeviation: measureSequenceDeviation(data)
  };
}
</code></pre>
<p>The code structure captures the user's keyboard navigation actions on specified forms using <code>captureKeyboardSequence(formId)</code>, which means that the user has entered keystrokes, such as tabbing and focusing between fields.</p>
<p>Using <code>extractNavigationFeatures(data)</code>, the code processes the Raw keyboard navigation sequence by calculating metrics. Lastly, the code loads a previously-trained ML model and provides the extracted features to the model to be classified into their respective categories along with a confidence score.</p>
<p>Any keyboard navigation anomalies detected with a confidence score of 0.8 or higher will be filtered. The detected keystroke sequences, type of anomaly, severity, and specific suggestions will be included in the final results report for later review by the user.</p>
<h3 id="heading-fuzzy-logic-paradigm-for-navigation-performance-scoring">Fuzzy Logic Paradigm for Navigation-Performance Scoring</h3>
<p>Collaborative feedback systems can help improve the virtual keyboard user experience. Fuzzy logic lets you combine multiple measurements – like focus visibility and tab order – into a single score that better reflects the actual user experience. (Source: <a href="https://www.researchgate.net/publication/392950031_Enhancing_User_Experience_of_Virtual_Keyboard_Through_Collaborative_and_Speed-Adaptive_Auditory-Vibrotactile_Feedback">Liu and others, ResearchGate</a>).</p>
<p>For example, the following code creates a fuzzy inference system that evaluates two inputs: Focus Visibility and Tab Order Logic. These two inputs are evaluated using fuzzy logic and associated rules to arrive at a single score representing the total efficiency of keyboard navigation for a given application.</p>
<pre><code class="language-python">function createKeyboardNavigationFuzzySystem() {
  // Define fuzzy variables
  const focusVisibility = new FuzzyVariable('focusVisibility', 0, 100);
  focusVisibility.addTerm('poor', new TriangularMF(0, 0, 40));
  focusVisibility.addTerm('adequate', new TriangularMF(30, 50, 70));
  focusVisibility.addTerm('excellent', new TriangularMF(60, 100, 100));
  
  const tabOrderLogic = new FuzzyVariable('tabOrderLogic', 0, 100);
  tabOrderLogic.addTerm('confusing', new TriangularMF(0, 0, 40));
  tabOrderLogic.addTerm('acceptable', new TriangularMF(30, 50, 70));
  tabOrderLogic.addTerm('intuitive', new TriangularMF(60, 100, 100));
  
  const navigationEfficiency = new FuzzyVariable('navigationEfficiency', 0, 100);
  navigationEfficiency.addTerm('inefficient', new TriangularMF(0, 0, 40));
  navigationEfficiency.addTerm('moderate', new TriangularMF(30, 50, 70));
  navigationEfficiency.addTerm('efficient', new TriangularMF(60, 100, 100));
  
  // Define fuzzy rules
  const rules = [
    'IF focusVisibility IS excellent AND tabOrderLogic IS intuitive THEN navigationEfficiency IS efficient',
    'IF focusVisibility IS poor OR tabOrderLogic IS confusing THEN navigationEfficiency IS inefficient',
    'IF focusVisibility IS adequate AND tabOrderLogic IS acceptable THEN navigationEfficiency IS moderate'
  ];
  
  return new FuzzyInferenceSystem([focusVisibility, tabOrderLogic], navigationEfficiency, rules);
}
</code></pre>
<p>The resulting score is meant to be more representative of a user’s experience with the keyboard navigation system than other existing methods of measuring user satisfaction. This fuzzy inference system assesses keyboard navigation quality based on multiple dimensions at the same time, yielding scores in a similar range to user-reported satisfaction measurements (Source: <a href="https://www.researchgate.net/publication/392950031_Enhancing_User_Experience_of_Virtual_Keyboard_Through_Collaborative_and_Speed-Adaptive_Auditory-Vibrotactile_Feedback">Liu and others, ResearchGate</a>).</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article has given you the tools and resources you’ll need to automate a UX audit of your app’s forms – from the initial setup through continuous integration.</p>
<p>You’ve learned:</p>
<ul>
<li><p>Three essential components of forms and the importance of addressing each component systematically.</p>
</li>
<li><p>How to link objectives directly with business KPIs and user outcomes.</p>
</li>
<li><p>How to set up automated testing for the specificity of errors, the timing of validation, and the direction for the next actionable step after an error.</p>
</li>
<li><p>How to review the hint text on your forms: proactive display, proximity to the field it assists, and accessibility.</p>
</li>
<li><p>How to validate keyboard navigation through verification of tab order, testing focus visibility, and using ARIA tags.</p>
</li>
<li><p>How to incorporate WCAG criteria into your automated tests and to incorporate Nielsen's 10 Heuristics.</p>
</li>
<li><p>How to prepare documentation for the handoff between Design and Development, using the "5Cs": Coverage, Completion, Consistency, Clarity, and Correctness.</p>
</li>
</ul>
<p><strong>Next steps:</strong></p>
<ul>
<li><p>Begin with a single high-impact form in your application (signup or checkout) and run the basic automated checks on error messages and keyboard flows.</p>
</li>
<li><p>Integrate one or two audit functions into your existing test suite to see how they surface issues you might have missed manually.</p>
</li>
<li><p>Create a centralized error and hint message library for your most critical forms to ensure consistency.</p>
</li>
<li><p>Gradually expand your audit coverage to additional forms and fields as you refine your automation approach.</p>
</li>
<li><p>Add these checks to your CI/CD pipeline so they run automatically on every pull request, catching regressions before they reach users.</p>
</li>
<li><p>Experiment with AI-powered anomaly detection for keyboard navigation patterns once your foundational audits are stable.</p>
</li>
</ul>
<p>Most importantly, remember that form UX optimization is an ongoing practice, not a one-time fix. Start with the forms that directly impact your conversion metrics, validate that your automated checks catch real user problems, and expand your coverage systematically. Your goal should be to build a reliable system that continuously protects your users from friction.</p>
<h3 id="heading-about-the-author">About the author</h3>
<p>Hope you enjoyed the article and found it helpful. I’ve been a contributor to freeCodeCamp for more than 8 years, and to make this piece more precise and detailed, I used some expert help.</p>
<p>I sincerely thank skilled designers from <a href="https://coaxsoft.com/">COAX Software</a> for the UX and accessibility guidelines, and the developers who provided the audit automation code snippets (who both wished to stay anonymous). The company has a deep expertise in <a href="https://coaxsoft.com/services/ux-audit-services">UI/UX design</a>.</p>
<p>To find out more about me and read more content on tech and digital, visit <a href="https://www.linkedin.com/in/oleg-romanyuk/">https://www.linkedin.com/in/oleg-romanyuk/</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Powerful Motion Graphics Frameworks for Developers ]]>
                </title>
                <description>
                    <![CDATA[ Motion graphics are no longer just eye candy. They have become a key part of how users experience software, whether it’s a mobile app, a website, or even for making animated explainer videos.  When users tap a button, they expect it to respond smooth... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/powerful-motion-graphics-frameworks-for-developers/</link>
                <guid isPermaLink="false">685595022e5abc4d8aad787e</guid>
                
                    <category>
                        <![CDATA[ UI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Fri, 20 Jun 2025 17:06:10 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750439122439/489ef402-89db-47b5-a392-4c0fdcd94d0a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Motion graphics are no longer just eye candy. They have become a key part of how users experience software, whether it’s a mobile app, a website, or even for making animated explainer videos. </p>
<p>When users tap a button, they expect it to respond smoothly. When data is loading, users expect some visual feedback. Even small touches, like a gentle bounce or a fading transition, can make an interface feel polished and professional.</p>
<p>For developers, motion graphics are now part of the job. Designers may create the initial assets, but it’s usually developers who bring them to life in the actual product. </p>
<p>That means knowing how to control animations with code, integrate them into app logic, and make sure they perform well across devices. </p>
<p>Fortunately, a number of powerful tools have emerged that make motion graphics more accessible to developers without requiring them to become expert animators.</p>
<p>Let’s dive into some of the best motion graphics tools that developers can use today, and why each one is worth learning.</p>
<h2 id="heading-lottie"><strong>Lottie</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750080168850/b8487ad6-5776-4c96-97a2-33cf30b752bb.png" alt="Lotte" class="image--center mx-auto" width="1400" height="612" loading="lazy"></p>
<p><a target="_blank" href="https://lottiefiles.com/">Lottie</a> has become one of the most widely used tools for integrating motion graphics into mobile apps and websites. </p>
<p>Originally developed by Airbnb, Lottie lets designers create animations in Adobe After Effects and export them as lightweight JSON files using the Bodymovin plugin. </p>
<p>As a developer, you don’t have to recreate complex animations manually or deal with heavy video files. Instead, you load the JSON file into your app using the Lottie library, and the animation plays natively.</p>
<p>One of Lottie’s biggest advantages is its cross-platform support. Whether you’re building for iOS, Android, the web, React Native, or Flutter, Lottie works the same way. </p>
<p>The animations are rendered as scalable vector graphics, so they stay sharp on any screen size or resolution. This makes them perfect for things like onboarding screens, button interactions, loading indicators, and even full-screen animated backgrounds.</p>
<p>Lottie also gives you a lot of control through code. You can play, pause, loop, or even dynamically change the speed of an animation. If you want an animation to start when a user scrolls to a certain point or clicks a button, you can easily hook into your app’s logic and control the animation’s state. </p>
<p>This flexibility makes Lottie a favorite for developers who want designer-level animations without the usual headaches of file size, performance, or cross-platform compatibility.</p>
<h2 id="heading-gsap"><strong>GSAP</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750080203585/ddcb08af-f25b-4b2c-8cbb-9d593baf2561.jpeg" alt="GSAP" class="image--center mx-auto" width="1280" height="640" loading="lazy"></p>
<p>While Lottie is great for pre-designed animations, sometimes you want full programmatic control over how elements move and interact. That’s where <a target="_blank" href="https://gsap.com/">GSAP</a>, short for GreenSock Animation Platform, really shines. </p>
<p>GSAP allows you to animate anything on the web: HTML elements, SVG graphics, Canvas drawings, and even WebGL content. It’s used by professional web developers and interactive designers around the world for its precision, performance, and flexibility.</p>
<p>With GSAP, you write animations directly in JavaScript. You’re not importing files created in a design tool. Instead, you describe the animations in code, which gives you complete control over timing, sequencing, and interaction. </p>
<p>You can chain multiple animations together, create synchronized timelines, and easily coordinate animations across multiple elements. The syntax is both simple and powerful, allowing you to start with basic effects and scale up to complex sequences as needed.</p>
<p>One of GSAP’s standout features is how well it handles performance. Animations stay smooth even when animating many elements at once, and the library takes care of browser quirks so you don’t have to worry about inconsistencies across platforms. </p>
<p>If you’ve ever struggled with CSS transitions or vanilla JavaScript animations, GSAP feels like a breath of fresh air. You get pixel-perfect control with readable and maintainable code, even as your animations grow more complex.</p>
<h2 id="heading-framer-motion"><strong>Framer Motion</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750080236390/a3a38be8-c11d-43ac-bcf8-0f89745f7607.png" alt="Framer Motion" class="image--center mx-auto" width="1600" height="691" loading="lazy"></p>
<p>If you’re building modern web apps with React, <a target="_blank" href="https://motion.dev/">Framer Motion</a> offers a different kind of power. </p>
<p>Unlike GSAP, which works everywhere, Framer Motion is built specifically for React’s component model. Instead of managing animations through external scripts or event listeners, you define them directly in your JSX code alongside the rest of your component logic.</p>
<p>This declarative approach means you simply describe what you want to happen, and Framer Motion takes care of the rest. You specify target values for things like position, opacity, or scale, and the library smoothly transitions from the current state to the new one whenever props change. </p>
<p>This makes it incredibly easy to animate things like page transitions, hover effects, collapsible panels, and other common UI interactions.</p>
<p>Framer Motion also supports more advanced features out of the box, such as gesture-based animations, layout transitions, and shared element transitions between different routes or components. </p>
<p>These kinds of features can be very challenging to implement manually, but Framer Motion makes them approachable even for developers who aren’t animation experts.</p>
<p>Another benefit is how naturally Framer Motion fits into the React ecosystem. Since you’re not writing separate animation code, your logic stays tightly integrated with your app state and component structure. This reduces bugs, simplifies maintenance, and helps keep your codebase clean and organised.</p>
<h2 id="heading-rive"><strong>Rive</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750080251167/6cbfc5ec-28cc-453d-9ea0-52633d4b5efe.jpeg" alt="Rive" class="image--center mx-auto" width="640" height="480" loading="lazy"></p>
<p><a target="_blank" href="https://rive.app/">Rive</a> represents a new way of thinking about motion graphics, one that blurs the line between design and code. </p>
<p>Unlike tools that focus only on timeline-based animations, Rive adds state machines and logic directly into the animation itself. This allows you to create interactive, real-time animations that respond to user input or application state changes.</p>
<p>In Rive’s editor, designers build both the visuals and the interaction logic. You can define how animations transition between different states based on triggers that your app can control. </p>
<p>As a developer, you don’t have to write complex animation logic yourself. Instead, you simply send events to the Rive runtime and let it handle the animation transitions.</p>
<p>For example, imagine a character that waves when a user taps the screen, then smiles if a task is completed. With Rive, the designer creates both the waving and smiling animations and wires up the logic that connects them. </p>
<p>You just tell the animation which state to enter based on your app’s data. The result feels dynamic and interactive, like a small game embedded into your UI.</p>
<p>Rive works across platforms, including web, mobile, and game engines, and the exported files are lightweight enough to use even in performance-sensitive environments. </p>
<p>It’s a tool that empowers both designers and developers to create richer experiences without a ton of back-and-forth or complicated handoffs.</p>
<h2 id="heading-threejs"><strong>Three.js</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750080261841/039f1365-e666-496c-a036-4e9f7c174329.png" alt="Three.js" class="image--center mx-auto" width="724" height="366" loading="lazy"></p>
<p>Sometimes, 2D animations aren’t enough. When you need true 3D motion graphics in the browser, <a target="_blank" href="https://threejs.org/">Three.js</a> is the go-to library for developers. </p>
<p>While not strictly a motion graphics tool in the traditional sense, Three.js allows you to create complex 3D scenes, animate objects, and build immersive experiences entirely with JavaScript.</p>
<p>Three.js abstracts much of the complexity of <a target="_blank" href="https://en.wikipedia.org/wiki/WebGL">WebGL</a>, making it more approachable for developers who may not have a deep background in computer graphics. You can load 3D models, apply materials and lighting, set up cameras, and create fully interactive environments that respond to user input.</p>
<p>Animation in Three.js can involve simple tasks like rotating a model or more complex sequences like animated camera moves or physics-based simulations. Because you have full access to the scene graph, you can control every detail of how your objects move and behave. </p>
<p>This opens up possibilities for product visualizations, interactive demos, educational tools, and even web-based games.</p>
<p>While Three.js has a steeper learning curve than the other tools mentioned here, the payoff is significant. You’re no longer limited to flat surfaces and basic transitions. With Three.js, you can build fully immersive experiences that were once only possible in native apps or games.</p>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<p>As motion graphics become more important in modern interfaces, developers have an expanding toolbox to help them deliver polished, interactive experiences. Each tool has its own strengths, depending on the project and platform.</p>
<p>As a developer, you don’t need to master all of these tools at once. Start with the one that fits your current project needs, and build your motion graphics skills from there. With practice, you’ll discover that motion isn’t just a visual extra — it’s part of how your software communicates, guides, and delights your users.</p>
<p>Hope you enjoyed this article. You can <a target="_blank" href="https://manishshivanandhan.com/">learn more about me</a> or <a target="_blank" href="https://www.linkedin.com/in/manishmshiva/">connect with me on Linkedidn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How UX and Marketing Are Saying the Same Things, Differently ]]>
                </title>
                <description>
                    <![CDATA[ Could it be that the key to designing a great product experience might be hidden in a 60-year-old marketing playbook? Well, for years, marketing and user experience (UX) have been treated as separate worlds. Marketing grabs attention and drives sales... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-ux-and-marketing-are-saying-the-same-things-differently/</link>
                <guid isPermaLink="false">680aa2e68a164048d5799e47</guid>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ux design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UXdesign  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ marketing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #Marketing strategy ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Customer Experience ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anamol Rajbhandari ]]>
                </dc:creator>
                <pubDate>Thu, 24 Apr 2025 20:45:26 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745520497294/c0cac6d6-feaf-4633-a8eb-18baf7f7f479.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Could it be that the key to designing a great product experience might be hidden in a 60-year-old marketing playbook?</p>
<p>Well, for years, marketing and user experience (UX) have been treated as separate worlds. Marketing grabs attention and drives sales, while UX makes products easy and enjoyable to use.</p>
<p>It may seem that they speak different languages, but if we dig a little deeper, we may find that they share a common foundation – often telling the same story in different words.</p>
<p>In this article, I’ll walk you through how the classic 4Ps of marketing (Product, Price, Place, and Promotion) intersect with UX to reveal how these disciplines can collaborate to create cohesive and effective product experiences.</p>
<h2 id="heading-the-four-ps-marketings-old-recipe-for-success"><strong>The Four P’s: Marketing’s Old Recipe for Success</strong></h2>
<p>In 1960, marketing professor E. Jerome McCarthy introduced what he called the “marketing mix,” famously distilled as the <a target="_blank" href="https://management.org/marketing-mix">Four P’s of marketing</a>. The four elements – <em>Product, Price, Place, Promotion</em> – became the cornerstone of modern marketing strategy.</p>
<p>This simple framework was about orchestrating everything a business offers: making the right product, at the right price, available at the right place, with the right promotion.</p>
<p>For decades, the 4Ps guided how companies aligned their offerings with customer needs and expectations. And even today, the 4Ps remain <em>“a foundational model in marketing,”</em> widely taught and practiced for one reason, which is that it works. Get each “P” right – build a product people want, price it fairly, distribute it conveniently, and communicate its value clearly – and that sets the stage for success.</p>
<p>Marketing hasn’t really changed at its core since McCarthy’s time. Sure, we’ve gone digital and added more Ps (like People, Process, and so on), but the heart of marketing is still understanding customers and delivering value.</p>
<p>What has changed is the context. As the century turned and the internet era took off, consumer behavior shifted dramatically. In this digital transformation, a new discipline rose to prominence alongside marketing: User Experience design, or just UX.  </p>
<p>The term “user experience” itself was popularized in the 1990s by <a target="_blank" href="https://careerfoundry.com/en/blog/ux-design/the-fascinating-history-of-ux-design-a-definitive-timeline/">cognitive psychologist Don Norman</a> to describe “all aspects of the end-user’s interaction with the company, its services, and its products”.</p>
<p>In essence, UX zooms in on how people feel when using a product or service to achieve their goals. It asks whether the product is usable, useful, and even enjoyable, and whether it meets the user’s needs without hassle.</p>
<p>As <a target="_blank" href="https://www.nngroup.com/articles/definition-user-experience/">Norman and Nielsen famously put it</a>, the first requirement for an exemplary UX is to meet the customer’s exact needs, without fuss or bother. And doing that well is the job of UX designers as much as it is the job of engineers, marketers, graphic designers, and interface designers.</p>
<p>In other words, great UX has always been a team sport, with marketing playing an important position in shaping user expectations.</p>
<p>Fast-forward to today, where marketing and UX are often seen as separate silos – but they’re really two sides of the same coin.</p>
<p>Both exist to create value for people. Both put the <em>user</em> (or <em>customer</em>) at the center of their decisions. Both aim to make a product desirable and worthwhile. The difference is that they just approach it from different directions.</p>
<p>Marketing is about increasing the <em>perceived value</em> of a product through messaging, brand, and offerings, while UX is about decreasing the <em>effort and friction</em> for the user <a target="_blank" href="https://www.nngroup.com/articles/ux-and-marketing/">through good design</a>. Put together, those efforts determine whether a product is actually worth it to the people using it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745405945475/1a64bb70-5c87-48a4-9688-f64eadb8868f.png" alt="The marketing mix. Source: https://www.techtarget.com/whatis/definition/Four-Ps" class="image--center mx-auto" width="1200" height="504" loading="lazy"></p>
<h2 id="heading-two-disciplines-one-goal-via-different-paths"><strong>Two Disciplines, One Goal via Different Paths</strong></h2>
<p>If we think of the journey as starting from when a customer first hears about a product to when they become a loyal user, marketing tends to focus on the “before”. Its responsibilities are customer acquisition, attracting the right people, and shaping their expectations.</p>
<p>On the other hand, UX focuses on the “after”. It takes over once the user is in the door, striving for customer satisfaction and retention while ensuring the product delivers on its promise.</p>
<ul>
<li><p>The marketer asks, <em>“How do we get people to notice and try this product?”</em></p>
</li>
<li><p>The UX designer asks, <em>“Now that they’re here, how do we make this experience fulfilling so they’ll stay (and come back)?”</em></p>
</li>
</ul>
<p>These are two halves of a continuous cycle. If marketing sets up a great promise and UX provides a great product experience, you’ve created something powerful: trust and loyalty.</p>
<p>If either side falls short, say, misleading hype from marketing or a clunky product from design, the whole experience breaks down. It’s no surprise, then, that the 4Ps matter just as much to UX as they do to marketing, as the 4Ps define the context in which users experience a product.</p>
<p>Let’s see how each P influences the user experience:</p>
<h3 id="heading-product-what-is-being-offered"><strong>Product:</strong> <strong><em>What is being offered?</em></strong></h3>
<p>This is the core of the experience. A product’s features and quality solve a problem for the user (or fail to). In marketing terms, a product is a bundle of benefits and values that fulfill a need. In UX terms, understanding the <em>right product</em> means researching what users truly need and designing the solution around that.</p>
<p>If the product doesn’t fit the user’s needs, no amount of pretty UI or even UX can fix that. McCarthy’s framework itself was about ensuring you have the <em>“right product”</em> to satisfy the target consumer.</p>
<h3 id="heading-price-how-much-does-it-cost-and-what-is-its-value"><strong>Price:</strong> <strong><em>How much does it cost, and what is its value?</em></strong></h3>
<p>Price is more than a number on a tag that sets an expectation in the user’s mind for what the product is worth. It also represents what the user is investing (money, but also time and effort). If an app is free but demands tons of personal data or time, that’s a “price” a user pays as well.</p>
<p>UX designers implicitly deal with price when they consider the effort a user must exert. A key principle in UX is minimizing “interaction cost”, which is the mental or physical effort to complete a task. To put it differently, a good UX strives to make the user’s side of the value exchange as smooth and fair as possible. When the price, which could be in dollars or effort, feels too high for the perceived benefit, the experience will suffer.</p>
<h3 id="heading-place-where-and-how-does-the-user-access-the-product"><strong>Place:</strong> <strong><em>Where and how does the user access the product?</em></strong></h3>
<p>This is about distribution and context. From a UX perspective, the questions to ask are whether it’s a mobile app used on the go, a website used from a desktop at work, or a physical retail store.</p>
<p>The marketing job is to put the product where its audience can find it. UX’s job is to ensure it works well in that context. A user’s environment (noisy bus vs. quiet office, 5-minute window vs. leisurely hour) can drastically affect their experience.</p>
<p>The best marketing in the world won’t help if the product isn’t available where users need it, and the best-designed interface will frustrate if it doesn’t fit the context of use. “Place” is part of the experience, like a stage on which your UX plays out.</p>
<h3 id="heading-promotion-what-does-the-user-hear-about-the-product-and-does-the-experience-live-up-to-that-message"><strong>Promotion:</strong> <strong><em>What does the user hear about the product, and does the experience live up to that message?</em></strong></h3>
<p>Promotion is how marketing sets expectations through advertising, branding, content, and word-of-mouth. It’s the story of the product. UX, in turn, is about delivering on that story. If the marketing promises one thing and the product delivers another, users feel disappointed or even deceived. Conversely, when promotion and experience align, the product feels trustworthy.</p>
<p>This is the reason why modern UX teams pay attention to onboarding messaging, in-app copy, and other content: they know every touchpoint either reinforces or contradicts what the user has been told. A good promotion can draw a user in, but only a matching UX will keep them in.</p>
<p>As the Nielsen Norman Group notes, both marketing and UX ultimately “<a target="_blank" href="https://www.nngroup.com/articles/ux-and-marketing/">aim to make a product or service desirable</a>” by increasing its perceived utility and value. Promotion creates the desire, and UX fulfills it.</p>
<p>Understanding these overlaps helps explain how most UX problems aren’t just UI problems or usability problems. Often, when a product fails for users, the culprit is a disconnect in one of the above areas.</p>
<p>Maybe the product didn’t actually solve the problem the user thought it would, which could be a product/expectation issue. Maybe the user felt the outcome wasn’t worth what they had to put in, which is a Price/value issue, with too much effort for too little reward. Perhaps they never fully understood the product’s value or got lost finding it, which is a Place/distribution issue. Or, they might have felt a little too let down because the hype didn’t match reality, which is a Promotion/trust issue.  </p>
<p>Many of these so-called “UX issues” boil down to expectation, value, and trust, the same concerns at the heart of marketing. But these are often completely ignored by UXers because they are deemed “out of scope”. And it is no coincidence that an actual seamless user experience tends to foster brand trust and loyalty.</p>
<p>So, when UX and marketing are in sync, the product feels right to the user on top of it working well. It meets the expectations set, provides real value, and earns the user’s confidence.</p>
<p><strong>Big picture:</strong> UX happens within a value exchange between a user and a product, and the 4Ps define many of the terms of that exchange. If a UX designer ignores things like pricing strategy or how the product is marketed, they might be missing half the story of the user’s experience.</p>
<h2 id="heading-a-shared-foundation-between-ux-and-the-4ps-and-why-it-matters-today"><strong>A Shared Foundation between UX and the 4Ps and Why It Matters Today</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745444445059/c71e0b15-0497-4439-a922-e591ca845035.png" alt="c71e0b15-0497-4439-a922-e591ca845035" class="image--center mx-auto" width="3840" height="2160" loading="lazy"></p>
<p>There’s often a quiet tension in organizations between the UX team and the marketing team. Marketers might joke that designers only care about “pretty screens,” and UX designers might grumble that marketers would sell anything with a flashy ad.</p>
<p>But at the end of the day, both teams are trying to solve the same problem. Both try to connect people with a product in a meaningful way, using their own processes and coming at it from different angles.</p>
<p>If users are churning or a product flops, it doesn’t really matter whether we call it a marketing failure or a UX failure – it’s usually a bit of both. This realization is exactly why the common ground between UX and marketing is so important in today’s digital product landscape.</p>
<p>Thinking with a marketing mindset, in fact, can make UX design stronger and more holistic. The classic marketing questions – <em>Who is the customer? What do they need? What will they pay or sacrifice? How do they discover us?</em> – are strategic questions that UX designers should ask as well. They force us to zoom out from the interface and consider the entire user journey.</p>
<p>The 4Ps framework is about interplay, as it is about tactics in isolation to ensure we’re aligning everything from the thing being sold to how people find it, what it costs, and where they get it. It asks whether we are even solving the right problem, in the right way, for the right people. And that should be a UX concern as much as a marketing concern, as that is the central question of making any product successful.</p>
<p>So why does this shared space between these two domains matter so much today? It’s because designing a great product is no longer confined to just the product’s interface or just the advertising around it, but with a cohesive experience from first impression to last use.</p>
<p>The lines between discovery, purchase, use, and re-use have blurred. A user can see an Instagram ad (promotion), click straight into an app store (place), download and try an app (product), and decide within minutes if it’s worth paying for full features (price). If any part of that chain breaks, say the ad misleads, or the app is confusing, or the value for cost isn’t there, the user is gone.</p>
<p>This means that teams need a common lens. The 4Ps offer exactly such a lens, bridging strategy and design. And maybe other marketing frameworks do, too. But the most important thing to remember is that marketing and UX are really playing in the same field of contributing to the total experience a customer has.</p>
<h2 id="heading-how-to-mindfully-collaborate-between-ux-and-marketing-teams"><strong>How to Mindfully Collaborate Between UX and Marketing Teams</strong></h2>
<p>Getting UX and marketing to work together can be messy in practice, as we’re merging different domains – and of course we may not get it right at first. The important thing is to be mindful of potential friction points as well as opportunities for collaboration.</p>
<p>It’s similar to running a new campaign. The first few attempts rarely deliver results, and throwing hands up after initial failures is common, but shortsighted. Teams could instead try openly sharing failures and frustrations, which is a rare thing to do, but that is how we can find things we usually don’t.  </p>
<p>We should let marketing look into UX’s messy usability tests, let UX dig through marketing’s failed campaigns, and ask each other simple, tough questions. Questions like, ‘<em>What would marketing do here? How might UX solve this problem?’</em> It can feel awkward, even frustrating, but doing this can uncover critical insights neither team could find alone.</p>
<p>Realistically, meaningful collaboration won’t happen by itself and thus might mean trying joint workshops once in a while – not every week, maybe just every few months – purely to understand each other's perspective. Marketers could step into the shoes of UX designers, and UX teams could tackle marketing challenges, engaging in a role-swapping session to build empathy.</p>
<p>We have to acknowledge from the get-go that these sessions could get uncomfortable, but that’s exactly the point. Solving big problems means dealing with uncertainty, making mistakes, and iterating patiently until we see what works.</p>
<p>Engaging in activities like working in the same sandbox, swapping insights and failures, role-playing each other’s perspective, asking “each other’s” questions as well as “each other” questions could help embrace frustration.</p>
<p>All in all, it’ll involve leaning into each other’s domains, understanding that persistence through repeated attempts is exactly how UX and marketing teams’ amalgamation might help solve great, challenging problems.</p>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>UX and marketing have always been two voices telling the same story. But for too long, we’ve drawn an imaginary line between them when in truth, they’re team members on a shared mission.</p>
<p>A UX designer talks about empathy and ease. A marketer talks about value and desire. Different words, but same goal to resonate with a human need.</p>
<p>The classic 4Ps of marketing should be taken as a mirror for UX that reflects a more holistic way to design. This definitely isn’t about doing marketing’s job and vice versa, but rather doing our job with a wider lens and striving to realize that what we thought was “their” language was always part of our own.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is a UX Engineer? User Experience Engineer Role Explained ]]>
                </title>
                <description>
                    <![CDATA[ I am currently a User Experience or UX Engineer for D2iQ. And lots of people ask me what exactly is a UX Engineer.  This question comes from designers and developers alike. So, I figured it was time to write about it to create awareness and demystify... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-a-ux-engineer/</link>
                <guid isPermaLink="false">66bc4cbf7fa38392bfab8132</guid>
                
                    <category>
                        <![CDATA[ user experience ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ux design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Natalie Pina ]]>
                </dc:creator>
                <pubDate>Fri, 25 Mar 2022 21:47:17 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/03/Blog-Header-1200x600-px--1--1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I am currently a User Experience or UX Engineer for D2iQ. And lots of people ask me what exactly is a UX Engineer. </p>
<p>This question comes from designers and developers alike. So, I figured it was time to write about it to create awareness and demystify the role.</p>
<p>This article will help you understand what a UX Engineer is, what their duties are, the required skillset, and it may even convince you to be come one yourself.</p>
<h2 id="heading-what-does-user-experience-mean">What Does User Experience Mean?</h2>
<p>Before we jump into the role of UX Engineer, let's take a brief moment to define User Experience. </p>
<p>Most people are familiar with UI, which refers to the user interface. The user interface is most commonly the screen in which user is interacting with, for example a website or application. </p>
<p>UX relates to the all encompassing experiences the end user has while using a product or service, UI included.</p>
<p>The significance of UX is undeniable. In <em>The User Experience Team of One</em>, author Leah Buley notes, </p>
<blockquote>
<p>“UX is a force for good. In an increasingly technological world, designing products with real people in mind helps us make sure that technology integrates in our lives in a human way. It’s a voice of reason, arguing that products and technology can support and even enrich our fundamental humanity.” </p>
</blockquote>
<h2 id="heading-who-are-ux-engineers">Who are UX Engineers?</h2>
<p>A UX Engineer (UXE) is the bridge between design and development. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/UXEngineer_Diagram.png" alt="Image" width="600" height="400" loading="lazy">
<em>Icon credit: Noun Project</em></p>
<h3 id="heading-engineers">Engineers</h3>
<p>UXE's are engineers first, with a working knowledge of design. Front end development skills are a prerequisite. A UXE cares deeply about the user experience and is heavily involved in impacting it.</p>
<blockquote>
<p>"Developers write the code and build the systems that make the experience real. That moment when a flat concept on a page becomes a working, functioning, interactive thing is like making life. It’s incredibly rewarding. It also enables them to see and understand how it will feel and function for the enduser." – <em>The User Experience Team of One</em></p>
</blockquote>
<h3 id="heading-designers">Designers</h3>
<p>UXEs can be particularly useful in conceptualization stages of design. They are able to help designers understand what is feasible and how much engineering effort it may take to achieve.</p>
<p>Some UXE's will contribute prototypes, wireframes, and design mockups. The amount of true design work can vary from company to company. </p>
<p>It is common for a UX Engineer to be working within a Design System. For example, my role at D2iQ includes maintaining a design system and component library.</p>
<h3 id="heading-advocates">Advocates</h3>
<p>A UXE will need to have empathy for both sides and be able to advocate for design or development. They may be required to push back on either side as an advocate. This is the reason they are considered the bridge between design and development.</p>
<p>A UXE may even need to advocate for UX itself within their organization, to create awareness and to build support for their work. This can be achieved through setting up a peer-to-peer learning community, lunch and learn meetings, and other methods to share and educate others.</p>
<p>You may find varying definitions of what a UX Engineer means. The lines are often blurred between UI Engineer, UX Engineer, and Design Technologist. Much of the role can depend on the company and what are the needs they want to fill with that role. </p>
<p>You may thrive as a UXE if you enjoy:</p>
<ul>
<li>Front end engineering</li>
<li>Styling with CSS specifically</li>
<li>Design thinking</li>
<li>Occasionally flexing some design skills</li>
<li>Participating in UX Research</li>
<li>Working with Design Systems</li>
<li>Creative leeway</li>
</ul>
<p>We'll dive deeper on the skills required as a UXE which may clarify what exactly it entails.</p>
<h3 id="heading-confusion-within-the-front-end">Confusion within the Front End</h3>
<p>I wanted to make a note on the confusion between UI Engineer, UX Engineer and Front End Engineer. These are often assumed to be the same role. That may or may not be the case, depending on what is in the job description. However, there are some notable differences.</p>
<p>UI Engineer is the most similar to a Front End Engineer. They're not entirely the same historically, but the line between the two has become blurry. They will work on the technical side of building the user interface. Working on the UI can easily start to bleed into UX topics as they are tightly coupled, which may be where the confusion arises. </p>
<p>On the other hand, a UX Engineer is the more design forward of the two. A UXE is a technical role that is intrinsically involved in the user's experience. They would be the one to consider "how is the user interacting with this button?", "how can I make it absolutely clear what this button does", and "how can I provider the user a better experience when using this button?" </p>
<p>On the other hand, a UI Engineer would generally ask themselves how to best match the design to engineer an efficient button. </p>
<p>This is of course glossing over the depths that each role can go into. UI Engineers can become more involved in UX if they take a conscious efforts to impact it. </p>
<p>The job description of UX Engineer might align more with what you would see under Design Technologist or Design System Engineer.</p>
<p>Overall, the term Front End can cover a broad range of individually complex topics and skillsets, which is why we are starting to see the need to define more specific roles within Front End. UX Engineer is among the more recent positions to become defined based on this.</p>
<h2 id="heading-required-skills-for-a-user-experience-engineer">Required Skills for a User Experience Engineer</h2>
<p>There are many skills that a UXE may possess that aren't limited to Front End development and design. Again, much of the role can be dictated by the company’s definition of the role and responsibilities. </p>
<p>Below are some of the key skills that would be most commonly applicable and helpful to have.</p>
<h3 id="heading-technical-skills">Technical Skills</h3>
<p><strong>Front End Development.</strong> This includes knowledge of HTML, CSS and JavaScript. You should also know popular JavaScript libraries such as React. This could additionally include testing, debugging, build tools, and dependency managers.</p>
<p><strong>CSS Specialists.</strong> It is important to note that the role requires in-depth knowledge of CSS. This could entail CSS architecture or working with preprocessors like Sass and Less. It's beneficial to have experience with CSS-in-JS libraries such as Styled Components and Emotion.</p>
<p><strong>UI/UX Design.</strong> This may be a mix of design related skills from prototyping to UX Principles to wire-framing. UXE’s may produce low-fidelity or high-fidelity design mockups. It is helpful to have experience with design tools such as Figma, Sketch, or InVision. Design systems could also be lumped into this category. It's valuable to understand the benefit of design systems, and knowing how to enforce the design standards in the UI. </p>
<p><strong>Storybook.</strong> Storybook is a tool to help engineers build, test, and display UI components. Working with Storybook will require additional niche technical know-how specific to this tool. There is a likelihood that if you are working with a design system and component library, the documentation is utilizing Storybook.</p>
<p><strong>Accessibility.</strong> To excel in this role, you need to understand accessibility guidelines. Caring for users means inclusive design. Products should not limit the type of user. Products should account for all users. Having technical skills to test and improve the accessibility of applications will be extremely beneficial.</p>
<p><strong>Responsive Design.</strong> Designers may only be able to mock up several screen size views such as mobile, tablet, and desktop. You'll be implementing those designs. There are gaps between each screen size mock which will require technical and decision making skills and for a seamless transition. These are the types of problems you will encounter and they impact the user experience.</p>
<h3 id="heading-less-technical-skills">Less Technical Skills</h3>
<p><strong>Empathy.</strong> This is a crucial skill for a UXE. They need to understand users in order to improve their experience. This includes having a passion for understanding how people think. Caring deeply about the impact you can have on user experiences will take you far in this field. </p>
<p><strong>Communication and Collaboration.</strong> UXEs are required to do a lot of cross-functional communication. They can speak with users, designers, developers, product owners, and stakeholders. They are held responsible for translations between design and engineering teams. There is a likelihood of contributing to documentation which uses written communication skills. This could include documenting style guides, components, or guides for users.</p>
<p><strong>Creativity.</strong> It may seem obvious that this would be a great skill to have based on the design factor of the role. UXE's have the opportunity to find creative solutions especially when design and development need to meet in the middle.</p>
<p><strong>User Experience Principles and Theories.</strong> Understanding the psychological aspect of UX will come in handy when making design decisions. Learning psychological heuristics is essential. The <a target="_blank" href="https://lawsofux.com/">Laws of UX</a> site is a great overview of these.</p>
<h2 id="heading-summary">Summary</h2>
<p>As design and engineering processes mature, there is a need for roles like UX Engineer, UX Researcher, UI/UX Designer, UI Engineer, and more, each with their own set of advanced skills. </p>
<p>By collaborating, these roles are able to come together to create top-notch experiences for users. The need for many of these roles has been increasing in recent years, especially with the recognization of the importance of design systems within organizations.</p>
<p>UX Engineers fill a void that can be beneficial to the handoff between design and development. We will continue to see an increasing amount of UX Engineering roles surface as the significance of this role becomes further recognized. </p>
<p>I love the blend of skills that I am able to use daily as a UXE. If you are a creative individual who wants to work closer with design teams this may be the perfect role for you too. </p>
<p>If you would like to learn more about working as a UX Engineer, feel free to reach out on <a target="_blank" href="https://twitter.com/ui_natalie">Twitter</a>. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is UX Design? User Experience Design Explained in Plain English ]]>
                </title>
                <description>
                    <![CDATA[ You might have heard of the term User Experience or UX design. But what does it mean exactly? In this article, I will explain what UX design is and talk about how to become a UX designer.  What is UX design? The term User Experience refers to how use... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/user-experience-design-what-does-a-ux-designer-do/</link>
                <guid isPermaLink="false">66b8da526b74ac70ba21e6cd</guid>
                
                    <category>
                        <![CDATA[ user experience ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ux design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jessica Wilkins ]]>
                </dc:creator>
                <pubDate>Mon, 04 Oct 2021 16:21:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/10/UX-design-pic.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You might have heard of the term User Experience or UX design. But what does it mean exactly?</p>
<p>In this article, I will explain what UX design is and talk about how to become a UX designer. </p>
<h2 id="heading-what-is-ux-design">What is UX design?</h2>
<p>The term User Experience refers to how users interact with a product or service. Whenever you login into a website, or play a game on your phone, your interaction with that application is considered user experience.</p>
<p>UX Design goes beyond digital applications. User Experience is relevant for any product or service that a user interacts with. </p>
<p>Other examples would include assembly guides for putting together furniture or a dining experience at a restaurant. </p>
<p>If you find a product to be easy to use and understand, then that would be considered a positive user experience. But if the product is confusing and frustrating then that would be considered a negative user experience. </p>
<p>Professional UX designers put a lot of thought into how a user interacts with a product to ensure that they have a positive experience. Negative experiences can lead to loss of revenue for a company if the user decides, based on their experience, to no longer use the product or service.</p>
<h2 id="heading-history-of-ux-design">History of UX design</h2>
<p>The term User Experience Design was first introduced in the early 1990's by Donald Arthur Norman. In 1993, Donald was working as a User Interface Architect for Apple when he decided to change his title to User Experience Architect. </p>
<p>This is what Donald had to say about inventing the term User Experience:</p>
<blockquote>
<p>“I invented the term because I thought Human Interface and usability were too narrow: I wanted to cover all aspects of the person’s experience with a system, including industrial design, graphics, the interface, the physical interaction, and the manual.”</p>
</blockquote>
<p>Donald is considered a leader and educator for User Experience Design. He is also an accomplished author with his best selling book The Design of Everyday Things.</p>
<p>Even though the term User Experience Design wasn't introduced until the early 90's, examples of UX design date back further than that. </p>
<p>Many people regard Walt Disney as one of the first UX designers because of his parks and resorts. </p>
<p>In the 1950's, Walt Disney wanted to create an amusement park that was fun for both adults and children. During those times, amusements parks were seen as dirty and seedy places that weren't appropriate for children. </p>
<p>But Disney wanted to change all of that and provide park goers with a positive experience. A lot of care went into the construction of the park by the designers and engineers ("Disney Imagineers").</p>
<p>One example of strong UX design at the parks is the number of options that attendees can choose from. The parks were designed to appeal to all types of guests. </p>
<p>Whether you are a teenager looking for thrill rides or a young family looking to ride Dumbo the Flying Elephant or the tea cups – there is something for everyone. </p>
<h2 id="heading-examples-of-bad-ux-design">Examples of bad UX design</h2>
<p>Anything that is considered overly complicated, confusing, and hard to navigate would be bad UX design. </p>
<p>One example of bad UX in websites would be broken or invalid links.</p>
<p>I have created an example with dummy text and links that don't go anywhere.</p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/jessica-wilkins/embed/PojvBvv" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>If this were a real website, the user experience would be pretty poor because a lot of time is wasted clicking on links that do not work. This can be frustrating because users need to access that information but it is not available. </p>
<p>Another example of poor user experience is constant pop up ads and messages. These types of sites make it difficult to enjoy the content because you are constantly being interrupted with popups. </p>
<p>In this example, I have created a fake blog site where three different pop up messages urge you to subscribe. </p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/jessica-wilkins/embed/qBjGMvw?editors=1010" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p>This is clearly annoying to the user because they can't even read the blog post and now want to leave the page. </p>
<h2 id="heading-what-does-a-ux-designer-do">What does a UX designer do?</h2>
<p>UX designers will test and research to make sure that products and services create a positive user experience. When designing a new product or service, the first step is to conduct user research to better understand the audience. </p>
<p>During this first phase, UX designers need to understand what the user is hoping to get out of the product and identify possible challenges the user might face with the product or service. </p>
<p>The next phase is to create a User Persona which serves as an example persona of a customer using the product or service. This type of tool helps UX designers identify what a user is looking for from the product and produce a positive experience. </p>
<p>The next phase is to think about the structure and layout of the product so the user can easily find the information they are looking for. UX designers will start to focus on the user flow which is the complete process a user goes through while interacting with the product. </p>
<p>The last step is to create a prototype and perform user testing. UX designers will study the results from those tests and make the necessary modifications to the product. </p>
<h2 id="heading-where-to-learn-ux-design">Where to learn UX design?</h2>
<p>There are plenty of free high quality courses you can take online to start learning about UX design. </p>
<p>I would suggest going through the <a target="_blank" href="https://www.coursera.org/professional-certificates/google-ux-design">Google UX Design Professional Certificate</a> on Coursera. Each of the seven classes are free to audit. </p>
<p>You can also <a target="_blank" href="https://www.freecodecamp.org/news/ui-ux-design-tutorial-from-zero-to-hero-with-wireframe-prototype-figma/">read this article and watch the associated YouTube course</a> for a good introduction to UX and UI Design.</p>
<h2 id="heading-salary-for-ux-designers">Salary for UX designers</h2>
<p>There are many different job titles for User Experience.</p>
<p>Here are some common job titles:</p>
<ul>
<li>User Experience Architect</li>
<li>User Experience Researcher</li>
<li>User Experience Designer</li>
</ul>
<p>It is important to note that salaries will differ depending on your location. You can use sites like <a target="_blank" href="https://www.indeed.com/">Indeed</a> or <a target="_blank" href="https://www.glassdoor.com/index.htm">Glassdoor</a> to research salaries.  </p>
<p>These are some example salaries for UX designers based in the United States. This data is being pulled from <a target="_blank" href="https://www.salary.com/">Salary.com</a>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/Screen-Shot-2021-10-04-at-6.21.03-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>I hope you enjoyed this article and best of luck on your UX journey. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add a Splash Screen to Your Flutter App ]]>
                </title>
                <description>
                    <![CDATA[ By Krissanawat In this article, we're going to learn how to integrate a splash screen in a Flutter app. But first, why is having a splash screen in your app essential? What is a Splash Screen? A splash screen is an initial screen that gets displayed ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-a-splash-screen-in-flutter-app/</link>
                <guid isPermaLink="false">66d4601d787a2a3b05af43d6</guid>
                
                    <category>
                        <![CDATA[ Flutter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ user experience ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 26 Aug 2021 16:30:17 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/08/photo-1603539240352-8f2cce3257c4.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Krissanawat</p>
<p>In this article, we're going to learn how to integrate a splash screen in a Flutter app. But first, why is having a splash screen in your app essential?</p>
<h2 id="heading-what-is-a-splash-screen">What is a Splash Screen?</h2>
<p>A splash screen is an initial screen that gets displayed right when the user launches the app, before the main page loads. It may not look like much because it's only shown for a short time. But splash screens can really pack a punch as they're the first impression of the app. </p>
<p>You may think that most users ignore them. But splash screens do have an impact, even subconsciously. They set the tone for the overall app theme and the user experience. </p>
<p>Think of a splash screen as a welcome screen for your app. They also help let your users know when there's a loading delay due to a network issue or other error. Because of all this, we as developers should know how to add a proper splash screen to our mobile applications.</p>
<h2 id="heading-splash-screen-overview">Splash Screen Overview</h2>
<p>Since splash screens are a valuable initial element in any app, you need to learn how to integrate them properly. So in this tutorial, we are going to learn how to do so in the Flutter ecosystem. </p>
<p>The exact steps are pretty simple because we'll use a package to help us integrate the screen called <a target="_blank" href="https://pub.dev/packages/splashscreen"><em>splashscreen</em></a>. This package allows us to set the splash screen as well as time the splash screen appears with just a few lines of code. And we don't have to touch any native codes. </p>
<p>So let's get started and learn how to add a simple splash screen containing text, an image, and a loading indicator. </p>
<h2 id="heading-create-a-new-flutter-project">Create a New Flutter Project</h2>
<p>First, we need to create a new Flutter project. For that, make sure that you have the Flutter SDK and other Flutter app development related components installed. </p>
<p>If everything is properly set up, then to create a project you can simply run the following command in whatever local directory you want:</p>
<pre><code>flutter create splashSceenExample
</code></pre><p>After the project has been set up, navigate inside the project directory and execute the following command in the terminal to run the project in either an available emulator or an actual device:</p>
<p><code>flutter run</code></p>
<p>After it's successfully built, you will get the following result on the emulator screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-74.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-install-the-splashscreen-package">How to Install the splashscreen Package</h3>
<p>Now that we have our flutter project up and running, we can install the required dependencies. Now, you could add a splash screen by tampering with the native code in the Android and iOS folders – but if you're not a native Android or iOS developer, this isn't something you'll need to know how to do. </p>
<p>Fortunately, we have the <em><a target="_blank" href="https://pub.dev/packages/splashscreen">splashscreen</a></em> package that makes it easy to add a splash screen in your Flutter app. The package offers widgets and various customization parameters to put up a simple introductory splash screen in your app. </p>
<p>In order to use it, you need to add it to your dependencies first. To do that, just copy the piece of code in the code snippet below and paste it into your <strong>pubspec.yaml</strong> file:</p>
<p><code>splashscreen: ^1.3.5</code></p>
<p>The package provides a <code>SplashScreen</code> widget that lets you display a splash screen before navigating to your app’s primary screen.</p>
<h2 id="heading-how-to-add-a-splash-screen-to-your-app">How to Add a Splash Screen to Your App</h2>
<p>Now, we are going to use the <code>SplashScreen</code> widget provided by the <em>splashscreen</em> package. The idea is to apply the <code>SplashScreen</code> widget to the <code>home</code> parameter of your <code>MaterialApp</code> widget. You can see the overall coding implementation in the code snippet below:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-comment">// This widget is the root of your application.</span>
  @override
  Wid<span class="hljs-keyword">get</span> <span class="hljs-title">build</span>(<span class="hljs-params">BuildContext context</span>) {
    <span class="hljs-keyword">return</span> MaterialApp(
      title: <span class="hljs-string">'Flutter Demo'</span>,
      <span class="hljs-attr">theme</span>: ThemeData(
        primarySwatch: Colors.blue,
        <span class="hljs-attr">visualDensity</span>: VisualDensity.adaptivePlatformDensity,
      ),
      <span class="hljs-attr">home</span>: SplashScreen(
        seconds: <span class="hljs-number">8</span>,
        <span class="hljs-attr">navigateAfterSeconds</span>:MyHomePage(title: <span class="hljs-string">'Flutter Demo Home Page'</span>),
        <span class="hljs-attr">title</span>: <span class="hljs-keyword">new</span> Text(
          <span class="hljs-string">'SplashScreen Example'</span>,
          <span class="hljs-attr">style</span>: <span class="hljs-keyword">new</span> TextStyle(
              fontWeight: FontWeight.bold,
              <span class="hljs-attr">fontSize</span>: <span class="hljs-number">20.0</span>,
              <span class="hljs-attr">color</span>: Colors.white),
        ),
        <span class="hljs-attr">backgroundColor</span>: Colors.lightBlue[<span class="hljs-number">200</span>],
      )
    );
  }
}
</code></pre><p>In this code, we have introduced the SplashScreen widget in the home parameter of the MaterialApp. There are several parameters we have configured inside the <code>SplashScreen</code> widget. Let's look at each one more closely.</p>
<ul>
<li><code>seconds</code>: The <code>seconds</code> option allows you to enter the time in seconds that you want the splash screen to be displayed. </li>
<li><code>navigateAfterSeconds</code>: This option allows you to define the Widget or Screen (preferably the Home Screen of the app) which is shown after the splash screen ends. </li>
<li><code>title</code> : This option let you add text to your splash screen. Here, we have used <code>Text</code> widget with some styles to do that. </li>
<li><code>backgroundColor</code> : This allows you to specify the overall background color of the splash screen.</li>
</ul>
<p>Alright, that was a simple configuration of a splash screen with text. This is what it'll look like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/splashGIF1--1-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here, you can see that the splash screen appears for few seconds before the default Home page loads. The loader is also shown by default. </p>
<p>But, we can control the visibility of the loader by applying the <code>useLoader</code> parameter in the <code>SplashScreen</code> widget, which can be either true or false.</p>
<h3 id="heading-how-to-add-a-custom-loader-to-your-splash-screen">How to Add a Custom Loader to Your Splash Screen</h3>
<p>We already have the loader in place by default. But, we can control its color and styling by using the <code>loaderColor</code> options as shown in the code snippet below:</p>
<pre><code>home: SplashScreen(
        seconds: <span class="hljs-number">8</span>,
        <span class="hljs-attr">navigateAfterSeconds</span>:MyHomePage(title: <span class="hljs-string">'Flutter Demo Home Page'</span>),
        <span class="hljs-attr">title</span>: <span class="hljs-keyword">new</span> Text(
          <span class="hljs-string">'SplashScreen Example'</span>,
          <span class="hljs-attr">style</span>: <span class="hljs-keyword">new</span> TextStyle(
              fontWeight: FontWeight.bold,
              <span class="hljs-attr">fontSize</span>: <span class="hljs-number">20.0</span>,
              <span class="hljs-attr">color</span>: Colors.white),
        ),
        <span class="hljs-attr">backgroundColor</span>: Colors.blue,
        <span class="hljs-attr">styleTextUnderTheLoader</span>: <span class="hljs-keyword">new</span> TextStyle(),
        <span class="hljs-attr">loaderColor</span>: Colors.white
      )
</code></pre><p>Now you'll get the result as shown in the demo below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/splashGIF2--1-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here, you can see that we've changed the color of the loader to white.</p>
<h3 id="heading-how-to-add-an-image-or-logo-to-a-splash-screen">How to Add an Image or Logo to a Splash Screen</h3>
<p>Now to make the splash screen look better, we can add an image or diagram – perhaps a logo or something similar. </p>
<p>The <code>SplashScreen</code> widget gives you two additional parameters to set the logo correctly in the splash screen. The <code>image</code> option lets you add an image from your assets or network, and the <code>photoSize</code> option allows you to specify the dimensions of the image. </p>
<p>It's better to add images from your assets because loading network images depends on connectivity and sometimes the image may not show up due to a slow internet connection. </p>
<p>So we'll need to get the image to our <strong>./assets</strong> directory and then register the path to it in our <strong>pubspec.yaml</strong> file. Then, we can use the <code>image</code> and <code>photoSize</code> options as shown in the code snippet below:</p>
<pre><code>home: SplashScreen(
        seconds: <span class="hljs-number">5</span>,
        <span class="hljs-attr">navigateAfterSeconds</span>:MyHomePage(title: <span class="hljs-string">'Flutter Demo Home Page'</span>),
        <span class="hljs-attr">title</span>: <span class="hljs-keyword">new</span> Text(
          <span class="hljs-string">'SplashScreen Example'</span>,
          <span class="hljs-attr">style</span>: <span class="hljs-keyword">new</span> TextStyle(
              fontWeight: FontWeight.bold,
              <span class="hljs-attr">fontSize</span>: <span class="hljs-number">20.0</span>,
              <span class="hljs-attr">color</span>: Colors.white),
        ),
        <span class="hljs-attr">image</span>: <span class="hljs-keyword">new</span> Image.asset(<span class="hljs-string">'assets/flut.png'</span>),
        <span class="hljs-attr">photoSize</span>: <span class="hljs-number">100.0</span>,        
        <span class="hljs-attr">backgroundColor</span>: Colors.blue,
        <span class="hljs-attr">styleTextUnderTheLoader</span>: <span class="hljs-keyword">new</span> TextStyle(),
        <span class="hljs-attr">loaderColor</span>: Colors.white
      )
</code></pre><p>This will be the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/splashGIF3--1-.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, we have the image placed at the top of our text. There are other options available as well which you can explore via the documentation of the splash screen package itself. </p>
<p>And there you have it! Keep in mind that this works on both Android and iOS and does not need separate implementations.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Adding a splash screen to your app doesn't have to be hard, thanks to the <em>splashscreen</em> plugin. The main aim of this tutorial was to show you how to integrate a splash screen into your Flutter app without having to touch the native code. </p>
<p>Here, you learned how to create a splash screen and include text, a loading indicator, and an image. Now, the challenge is to use the remaining parameters provided by the <code>SplashScreen</code> widget. </p>
<p>Remember that a nice splash screen also helps alleviate any anxiety a user might have while launching your app. So, it does provide mental health benefits as well. </p>
<p>Just keep in mind that the <code>splashcreen</code> plugin's functionality is a bit limited. If you want to create a custom splash screen with full control over what you can add to it, then you will have to go into the native code. Still, for simple splash screens, this plugin does the job. </p>
<p>Lastly, you can get inspiration for your <a target="_blank" href="http://instaflutter.com/">Flutter App</a> from others that are already out there.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Navigating my seat at the product table as a self-taught designer. ]]>
                </title>
                <description>
                    <![CDATA[ By Kim Thuy Tu Two years ago, I switched from medicine and redesigned Instagram. Three months after, I packed what I could fit into my carry-on and two moving boxes, and flew to Saigon to become Christina’s second product designer. Fast forward to to... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/navigating-my-seat-at-the-product-table-as-a-self-taught-designer/</link>
                <guid isPermaLink="false">66d45f6738f2dc3808b790bd</guid>
                
                    <category>
                        <![CDATA[ leadership ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Life lessons ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Self Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ startup ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 27 Sep 2019 03:44:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/09/1_gc1cMHEivelCAmhr4Z33sw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Kim Thuy Tu</p>
<p><strong>Two years ago, I switched from medicine and</strong> <a target="_blank" href="https://medium.com/free-code-camp/i-wanted-to-see-how-far-i-could-push-myself-creatively-so-i-redesigned-instagram-1ff99f28fa8b"><strong>redesigned Instagram</strong></a><strong>.</strong></p>
<p>Three months after, I packed what I could fit into my carry-on and two moving boxes, and flew to Saigon to become <a target="_blank" href="http://christinas.vn">Christina’s</a> second product designer. Fast forward to today and I am now their Head of Product.</p>
<p>I can still remember my first task on the job: creating color swatches for our tour guide’s awesome new helmets. It might sound like a simple feat, but after trying out hundreds of color combinations and learning a thing or two about color theory, I was pretty proud of the results.</p>
<p>As Christina’s grew from 100 to well over 450+ team members spanning all across Vietnam, so did my responsibilities. From tour guide helmets to redesigning the company’s flagship communication app to then launching it for <a target="_blank" href="https://www.twohearts.app/inbox-app/">Airbnb hosts all over the world to use</a>, its been a crazy (but fun) ride.</p>
<p>As I look forward to my next journey back to the States, I wanted to reflect on my experiences by sharing what I’ve learned along the way as someone who started with zero knowledge about product design and technology.</p>
<p>Let’s be clear — I still feel like I know nothing. I just know <em>a little bit less of nothing</em> than the day before.</p>
<hr>
<h2 id="heading-trust-your-gut-when-it-comes-to-recruitment">Trust your gut when it comes to recruitment.</h2>
<p>If you, your team, and your culture are playing to the same tune — you <strong>will</strong> know whether the candidate is a good fit (or not). As a rule of thumb, my go-to question after assessing a candidate’s technical skill is:</p>
<blockquote>
<p><em>“How did this person make me</em> <strong><em>feel</em></strong><em>?”</em></p>
</blockquote>
<p>My goal for going into any interview is to gain a better understanding of who the candidate is beyond what is on their resume and what their motivations are for arriving in this room with me. If I left the interview feeling more confused and conflicted than I did going in, it’s probably a good sign that this candidate is not the one. If I left the room feeling energized and excited, s/he is most likely a keeper.</p>
<p>Hire someone you would be excited to work with and most importantly, trust your gut instinct.</p>
<h2 id="heading-be-consistent-in-expressing-your-values">Be consistent in expressing your values.</h2>
<p>From creating wireframes to leading a team of developers, I knew it was important to establish our design and engineering principles early. It helps guide us in making product decisions, examining trade-offs during development, and uniting us stronger as a team.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/0_rBRGudVZsC_HHsVi.png" alt="Image" width="600" height="400" loading="lazy">
<em><em>Our team’s north star ?</em></em></p>
<p>An example of when we put our principles to the test was when my CTO had fixed a bug only to have it spam our users with <strong>hundreds</strong> of push notifications within a span of minutes.</p>
<p>I suggested to my CTO that he should write a post to be considerate of our users, take accountability, and explain what had happened so that our users can empathize with us through our immediate transparency. It will also be the kind of leadership that our junior engineers can learn from. And he did.</p>
<p>Instead of receiving any backlash, his post was received with likes and heart-eye emojis. Not only did our principles became a model for how we communicated as a team and developed our products, but it also forged the path for building a trusting relationship with our users.</p>
<blockquote>
<p>It goes without saying that leaders lead best through their actions, and not only by what they have to say.</p>
</blockquote>
<p>Now whenever there’s a bug (not saying it happens often), <a target="_blank" href="https://en.wikipedia.org/wiki/Desensitization_%28psychology%29">our users are much more forgiving and understanding of it</a>. Not only that, but the other engineers on our team started to follow his example and took accountability for their own missteps as well.</p>
<h2 id="heading-dont-underestimate-the-power-of-11-meetings-because-they-are-so-so-important">Don’t underestimate the power of 1:1 meetings, because they are so, so important.</h2>
<p>Whether you’re a designer or the CEO of a company, 1:1 meetings will always be the bread and butter for building a personal connection with your team. My engineers and I have weekly 1:1 meetings to QA the state of our product and pending features. To my engineers, it might be just a routine product QA. To me, it’s a perfect window of opportunity for me to get to know them on a personal level, address concerns they might have, and provide insights to help them find more value in their work.</p>
<p>If you’re looking for mentorship or growth in your career, I suggest scheduling 1:1 meetings with your team leader. First, it shows initiative. Second, you might also be surprised by the feedback and support you get in return. Before reaching out, make sure you understand what your goal is for the meeting. Is it to understand how you’re doing in your role? Is it to ask for additional remote days? After figuring out what your objective is, <strong>make sure to communicate it</strong>. This will help give your team leader ample time to prepare and keep the meeting focused.</p>
<h2 id="heading-creating-a-process-is-great-but-staying-flexible-is-even-better">Creating a process is great, but staying flexible is even better.</h2>
<p>Create processes, but <strong>plan for disruption</strong>. This can mean one of two things. One, the process you created didn’t work out as intended. Two, the process you created worked, but it ended up being discarded somewhere along the ever-evolving development process. This is especially true for startups during their <a target="_blank" href="https://hackernoon.com/navigating-the-stages-of-hyper-growth-6201d65eaaa8">hyper-growth stage</a> when you have many cross-functional teams working together to build and ship a product. When this happens, you have to be able to quickly switch gears, and adopt new <a target="_blank" href="https://fs.blog/mental-models/">mental models</a>, while pushing the overall product vision forward.</p>
<p>So instead of looking for an evergreen process, make your process of implementing and iterating <em>evergreen</em>.</p>
<h2 id="heading-figma-is-king">Figma is king.</h2>
<p>This article is not sponsored by <a target="_blank" href="https://medium.com/u/bf1152b11387">Figma</a>, but I figured this would be a great chance for me to give this amazing team (and product) a shoutout. Before Figma, our design team at Christina’s was getting around with using Sketch for design, Zeplin for hand-off, and Abstract for version control. It was a lot of tools but we had figured out a process that worked for us. Intrigued by Figma’s approach to design and collaboration, I decided to test out the tool to see for myself.</p>
<p>With Figma, design to developer handoff became almost instantaneous. In addition to the speed and efficiency, we also saved a lot of money in not having to use multiple software to maintain our design system, version control, and hand-offs. Since then, our entire product team has switched over to using Figma, and we haven’t looked back since.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/1_VnqX4GVtfIs4pPPl37172w.png" alt="Image" width="600" height="400" loading="lazy">
<em>Thanks Figma ✌?</em></p>
<h2 id="heading-work-politics-will-always-be-a-thing-but-it-doesnt-mean-you-have-to-be-a-part-of-it">“Work politics will always be a thing, but it doesn’t mean you have to be a part of it.”</h2>
<p>My COO said this to me during one of our lunch conversations after I had told him my reason for not wanting to accept the promotion to Head of Product.</p>
<p>With my previous role as a product designer/owner, I was able to influence business decisions, resolve problems, and focus on building products from behind the shadows, politics-free. However, when he said this to me, it made me realize that it’s not about the situation or the environment, but rather how I choose to react (or not react) to it.</p>
<p>More importantly, he made me realize that my new role will only put me in a better position to squash any office politics (with my killer resting face), reinforce our core values, and further protect the positive and empowering culture we have built together.</p>
<h2 id="heading-start-building-your-persona-capital-early">Start building your persona capital early.</h2>
<p>A persona is in short — a representation of a target audience or a person. Research shows it takes about 3 seconds for people to form a perception of you upon the initial meeting. <a target="_blank" href="https://www.businessinsider.com/science-of-first-impressions-2015-2">Sometimes even before you’ve even spoken a word</a>. Now consider this in terms of all the micro-interactions you might have with your colleagues, clients, and business partners day-to-day. Add in impromptu slack messages, random hallway exchanges, desk drop-ins, meetings, and company events — now you have given every person you’ve interacted with countless seconds to form their opinion of you.</p>
<p>What kind of team member would you like to be? What kind of leader do you want to be perceived as? What do you want to be known for? Have these questions answered before you join any team or company — or someone else will answer them for you.</p>
<blockquote>
<p><em>If you want to be perceived as a competent, reliable, and self-sufficient person — show it and own it every opportunity you get.</em></p>
</blockquote>
<p>Once you build your persona capital, it’ll be one of your most valuable assets when communicating with stakeholders, influencing key decisions, and working with cross-functional teams.</p>
<h2 id="heading-imposter-syndrome-never-truly-goes-away-but-it-does-get-easier">Imposter syndrome never truly goes away, but it does get easier.</h2>
<p>Several months after joining Christina’s, I had a heart-to-heart with my CTO. <a target="_blank" href="https://medium.com/the-year-of-the-looking-glass/the-imposter-syndrome-9e23e2326d88">I told him how I felt like an imposter</a>. I told him how I felt like everything I’ve achieved up to this point had all been attributed to luck. It also didn’t help that I’ve never had any formal design education. I’m afraid that I was going to be exposed as a fraud one day. I was upfront about my personal assessment, and honestly, it felt good to finally say it out loud.</p>
<p>What he said next shocked me:</p>
<blockquote>
<p>he told me he felt the same.</p>
</blockquote>
<p>I was in disbelief and all I could muster was… really? This made me realized that this so-called imposter syndrome is perfectly normal, and it can happen to anyone regardless of age, sex, and experience. If anything, it just means you’re a humble person with <em>really</em> high expectations of yourself.</p>
<p>It’s been a couple of years since that exchange, and since then, I’ve felt less and less like an imposter. If you’re feeling these insecurities, share it with someone you trust. It’ll help relieve some of the burden and guilt.</p>
<p>One reassuring thing I’ll add is this — it will only get easier with time as long as you show up, put in the work, and commit to continuously learn.</p>
<p>Remember, you’ve earned your spot at the table. The only person that you need to convince now is <strong>yourself</strong>.</p>
<h3 id="heading-your-harshest-critic-is-always-going-to-be-yourself-dont-ignore-that-critic-but-dont-give-it-more-attention-than-it-deserves">“Your harshest critic is always going to be yourself. Don’t ignore that critic but don’t give it more attention than it deserves. </h3>
<p>— <a target="_blank" href="https://www.brainyquote.com/quotes/michael_ian_black_494912">Michael Ian Black</a>”</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Building colorful, springy components using React Spring and Tinycolor ]]>
                </title>
                <description>
                    <![CDATA[ By Stephen McLean Recently, I decided to build a web application to allow designers and developers to generate variants for colors and to check color accessibility. In this post, I would like to give you a walkthrough of how I built some of the compo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/building-colorful-springy-components-using-react-spring-and-tinycolor/</link>
                <guid isPermaLink="false">66d461493dce891ac3a96824</guid>
                
                    <category>
                        <![CDATA[ Accessibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 05 Jul 2019 15:49:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/07/philip-veater-AKmdNgzZESM-unsplash-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Stephen McLean</p>
<p>Recently, I decided to build <a target="_blank" href="https://rainbo.xyz/">a web application</a> to allow designers and developers to generate variants for colors and to check color accessibility. In this post, I would like to give you a walkthrough of how I built some of the components I would use in that app.</p>
<p>Full source code for the application can be found at the end of this article, along with a link to a Storybook instance with all of the described components.</p>
<h2 id="heading-dependencies">Dependencies</h2>
<p>To help me build these components I used <a target="_blank" href="https://github.com/bgrins/TinyColor">Tinycolor</a>, a library with a range of color utility functions which you can use to manipulate, transform, and represent colors.</p>
<p>I have also used <a target="_blank" href="https://www.react-spring.io/">React Spring</a>, which is a spring physics based library that allows you to add animations to your project really easily.</p>
<h2 id="heading-color-tile">Color Tile</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/Color-Tile-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Color Tile Designs</em></p>
<p>The simplest component out of our list, the color tile will serve as a building block for other components. The responsibility of this component is to display a color, along with its name and HEX value.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> TILE_SIZES = {
  <span class="hljs-attr">sm</span>: <span class="hljs-string">"2.5rem"</span>,
  <span class="hljs-attr">md</span>: <span class="hljs-string">"4rem"</span>,
  <span class="hljs-attr">lg</span>: <span class="hljs-string">"6rem"</span>
};

<span class="hljs-keyword">const</span> ColorTile = <span class="hljs-function">(<span class="hljs-params">{
  color,
  name,
  hideName,
  hideHex,
  size,
  className,
  customTileStyle,
  ...otherProps
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> containerClass = cx(styles.container, className);

  <span class="hljs-keyword">const</span> tileClass = cx(styles.tile, {
    <span class="hljs-string">"margin-bottom--xxs"</span>: !hideName || !hideHex
  });
  <span class="hljs-keyword">const</span> dimension = TILE_SIZES[size];
  <span class="hljs-keyword">const</span> tileStyle = {
    <span class="hljs-string">"--color-tile-width"</span>: dimension,
    <span class="hljs-string">"--color-tile-height"</span>: dimension,
    <span class="hljs-string">"--color-tile-bg"</span>: color,
    <span class="hljs-string">"--color-tile-border-color"</span>: <span class="hljs-string">"transparent"</span>,
    ...customTileStyle
  };
  <span class="hljs-keyword">const</span> tile = <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{tileStyle}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{tileClass}</span> /&gt;</span></span>;

  <span class="hljs-keyword">const</span> nameClass = cx(<span class="hljs-string">"text--colors-grey-lighten-30"</span>, {
    <span class="hljs-string">"margin-bottom--xxs"</span>: !hideHex
  });

  <span class="hljs-keyword">const</span> hex = useMemo(<span class="hljs-function">() =&gt;</span> tinycolor(color).toHexString(), [color]);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{containerClass}</span> {<span class="hljs-attr">...otherProps</span>}&gt;</span>
      {tile}
      {!hideName &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{nameClass}</span>&gt;</span>{name}<span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span>}
      {!hideHex &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text--colors-grey-lighten-30"</span>&gt;</span>{hex}<span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

ColorTile.propTypes = {
  <span class="hljs-comment">/**
   * Color to display
   */</span>
  <span class="hljs-attr">color</span>: PropTypes.string.isRequired,
  <span class="hljs-comment">/**
   * Name of the color
   */</span>
  <span class="hljs-attr">name</span>: PropTypes.string,
  <span class="hljs-comment">/**
   * Hide the name text if true
   */</span>
  <span class="hljs-attr">hideName</span>: PropTypes.bool,
  <span class="hljs-comment">/**
   * Hide the hex color value display if true
   */</span>
  <span class="hljs-attr">hideHex</span>: PropTypes.bool,
  <span class="hljs-comment">/**
   * Size of the tile
   */</span>
  <span class="hljs-attr">size</span>: PropTypes.oneOf([<span class="hljs-string">"sm"</span>, <span class="hljs-string">"md"</span>, <span class="hljs-string">"lg"</span>]),
  <span class="hljs-comment">/**
   * Custom styles to apply to the tile element
   */</span>
  <span class="hljs-attr">customTileStyle</span>: PropTypes.object
};

ColorTile.defaultProps = {
  <span class="hljs-attr">size</span>: <span class="hljs-string">"md"</span>,
  <span class="hljs-attr">hideName</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">hideHex</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">customTileStyle</span>: {}
};
</code></pre>
<h4 id="heading-notes-on-the-implementation">Notes on the implementation</h4>
<ol>
<li>Line 17, and line 19 might look slightly strange if you’re not familiar with the excellent <a target="_blank" href="https://www.npmjs.com/package/classnames">classnames</a> library. Basically, the classnames library allows you to concatenate and conditionally apply CSS classes to your elements.</li>
<li>On line 36 you can see that we calculate the HEX string of the color passed in. Since we’re using the color prop passed in directly in the CSS, it can be in any acceptable CSS color format, not just HEX. It could be an rgba string for example. This is where Tinycolor comes in. We can give it any of those formats and it returns a nicely formatted HEX string we can display along with our tile.</li>
<li>Sticking with line 36, you might also have noticed that the function to calculate the HEX string is wrapped in <code>useMemo</code> . This is because we only want to compute this value if the color changes. We can avoid recalculating if any of the other props change which might cause a rerender. I’m still learning the new Hooks API, so this might not be the most appropriate usage of <code>useMemo</code> since it’s probably not a particularly expensive operation, but I think it was a nice way to handle it regardless. You can learn more about the <code>useMemo</code> function or Hooks in general <a target="_blank" href="https://reactjs.org/docs/hooks-reference.html#usememo">here</a>.</li>
</ol>
<pre><code class="lang-css"><span class="hljs-selector-class">.tile</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-built_in">var</span>(--color-tile-width);
  <span class="hljs-attribute">height</span>: <span class="hljs-built_in">var</span>(--color-tile-height);
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">var</span>(--color-tile-bg);
  <span class="hljs-attribute">border</span>: <span class="hljs-number">3px</span> solid <span class="hljs-built_in">var</span>(--color-tile-border-color);
  <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: inline-flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">align-items</span>: center;
}
</code></pre>
<h4 id="heading-notes-on-the-styling">Notes on the styling</h4>
<p>The styling of our tile is really simple. We have the tile itself which takes its dimensions and color from the variables we pass in.</p>
<p>Then, we have the container which holds the tile, the color name, and the HEX value. It’s a simple flex container that keeps our elements aligned.</p>
<h2 id="heading-color-picker">Color Picker</h2>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*60aXsgfuTUd0yYPBvhl71w.png" alt="Image" width="454" height="786" loading="lazy">
<em>Color Picker Designs</em></p>
<p>For our Color Picker, we are going to reuse the Color Tile component, along with a picker from the <a target="_blank" href="https://casesandberg.github.io/react-color/">react-color</a> package.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> PropTypes <span class="hljs-keyword">from</span> <span class="hljs-string">"prop-types"</span>;
<span class="hljs-keyword">import</span> { ChromePicker } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-color"</span>;

<span class="hljs-keyword">import</span> ColorTile <span class="hljs-keyword">from</span> <span class="hljs-string">"../ColorTile/ColorTile"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./ColorPicker.module.scss"</span>;

<span class="hljs-keyword">const</span> ColorPicker = <span class="hljs-function">(<span class="hljs-params">{ color, onChange, className, tileClassName }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [isPickerOpen, setPickerOpen] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">const</span> onSwatchClick = <span class="hljs-function">() =&gt;</span> {
    setPickerOpen(!isPickerOpen);
  };

  <span class="hljs-keyword">const</span> onColorChange = <span class="hljs-function"><span class="hljs-params">color</span> =&gt;</span> {
    onChange(color.hex);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{className}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ColorTile</span>
        <span class="hljs-attr">color</span>=<span class="hljs-string">{color}</span>
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onSwatchClick}</span>
        <span class="hljs-attr">hideHex</span>=<span class="hljs-string">{false}</span>
        <span class="hljs-attr">size</span>=<span class="hljs-string">"lg"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{tileClassName}</span>
      /&gt;</span>

      {isPickerOpen &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.popover}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.cover}</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onSwatchClick}</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">ChromePicker</span> <span class="hljs-attr">color</span>=<span class="hljs-string">{color}</span> <span class="hljs-attr">onChangeComplete</span>=<span class="hljs-string">{onColorChange}</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

ColorPicker.propTypes = {
  <span class="hljs-comment">/**
   * Currently selected color value
   */</span>
  <span class="hljs-attr">color</span>: PropTypes.string,
  <span class="hljs-comment">/**
   * Callback fn for when the color changes
   */</span>
  <span class="hljs-attr">onChange</span>: PropTypes.func,
  <span class="hljs-comment">/**
   * Custom classes to apply to the color tile
   */</span>
  <span class="hljs-attr">tileClassName</span>: PropTypes.string
};

ColorPicker.defaultProps = {
  <span class="hljs-attr">onChange</span>: <span class="hljs-function">() =&gt;</span> {}
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ColorPicker;
</code></pre>
<h4 id="heading-notes-on-the-implementation-1">Notes on the implementation</h4>
<p>Our color picker is composed of a <code>ColorTile</code> which shows the currently selected color, along with its HEX value, and a <code>ChromePicker</code> from the <code>react-color</code> library which actually allows us to select a color.</p>
<p>We have some state which controls whether the <code>ChromePicker</code> is visible or not, and a callback function to let whatever component is using our picker know when the color changes. <code>react-color</code> provides lots of information when the color changes, but the hex value was enough for my purposes as you can see on line 17.</p>
<h2 id="heading-color-list">Color List</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/Color-List--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Color List Designs</em></p>
<p>Our Color List component takes a list of colors and renders them as a list containing color tiles. Our Color List is intended to show a base color as a slightly larger tile, with the remaining tiles representing the variants of the base shown as smaller tiles. We also allow naming our list, and this will be used to display the name of the base color.</p>
<p>Our Color List also brings the “springy” part of this walkthrough. The tiles will be animated on entry using React Spring ?</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> ROW_DIRECTION = <span class="hljs-string">"row"</span>;
<span class="hljs-keyword">const</span> COL_DIRECTION = <span class="hljs-string">"col"</span>;
<span class="hljs-keyword">const</span> ALL_DIRECTIONS = [ROW_DIRECTION, COL_DIRECTION];

<span class="hljs-comment">/**
 * Renders a list of colors
 */</span>
<span class="hljs-keyword">const</span> ColorPaletteList = <span class="hljs-function">(<span class="hljs-params">{
  name,
  colors,
  direction,
  onColorClick,
  onColorDoubleClick,
  animationRef,
  getCustomTileStyle,
  renderTileBy,
  ...otherProps
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> headingClass = cx(<span class="hljs-string">"margin-bottom--xs"</span>, {
    <span class="hljs-string">"text--align-left"</span>: direction === ROW_DIRECTION,
    <span class="hljs-string">"text--align-center"</span>: direction === COL_DIRECTION
  });

  <span class="hljs-keyword">const</span> containerClass = cx({
    [styles.containerCol]: direction === COL_DIRECTION,
    [styles.containerRow]: direction === ROW_DIRECTION
  });

  <span class="hljs-keyword">const</span> tileClass = cx({
    <span class="hljs-string">"margin-bottom--xs"</span>: direction === COL_DIRECTION,
    <span class="hljs-string">"margin-right--xs"</span>: direction === ROW_DIRECTION
  });

  <span class="hljs-keyword">const</span> trailMargin =
    direction === COL_DIRECTION ? <span class="hljs-string">"marginBottom"</span> : <span class="hljs-string">"marginRight"</span>;
  <span class="hljs-keyword">const</span> trails = useTrail(colors.length, {
    <span class="hljs-attr">from</span>: { [trailMargin]: <span class="hljs-number">20</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span> },
    <span class="hljs-attr">to</span>: { [trailMargin]: <span class="hljs-number">0</span>, <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span> },
    <span class="hljs-attr">ref</span>: animationRef
  });

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> {<span class="hljs-attr">...otherProps</span>}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h4</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{headingClass}</span>&gt;</span>{name || ""}<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{containerClass}</span>&gt;</span>
        {trails.map((trailProps, idx) =&gt; {
          const color = colors[idx];
          const onClick = () =&gt; onColorClick(color);
          return (
            <span class="hljs-tag">&lt;<span class="hljs-name">animated.div</span>
              <span class="hljs-attr">key</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">animated-tile-</span>${<span class="hljs-attr">color.name</span>}<span class="hljs-attr">-</span>${<span class="hljs-attr">idx</span>}`}
              <span class="hljs-attr">style</span>=<span class="hljs-string">{trailProps}</span>
            &gt;</span>
              {renderTileBy(color, tileClass, onClick, false, false)}
            <span class="hljs-tag">&lt;/<span class="hljs-name">animated.div</span>&gt;</span>
          );
        })}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

ColorPaletteList.propTypes = {
  <span class="hljs-comment">/**
   * Name of the list
   */</span>
  <span class="hljs-attr">name</span>: PropTypes.string,
  <span class="hljs-comment">/**
   * The list of colors to display
   */</span>
  <span class="hljs-attr">colors</span>: PropTypes.arrayOf(
    PropTypes.shape({
      <span class="hljs-attr">color</span>: PropTypes.string,
      <span class="hljs-attr">name</span>: PropTypes.string,
      <span class="hljs-attr">isMain</span>: PropTypes.bool
    })
  ).isRequired,
  <span class="hljs-comment">/**
   * Determines the layout of the tiles
   */</span>
  <span class="hljs-attr">direction</span>: PropTypes.oneOf(ALL_DIRECTIONS),
  <span class="hljs-comment">/**
   * Callback for when a color in the list is clicked
   */</span>
  <span class="hljs-attr">onColorClick</span>: PropTypes.func,
  <span class="hljs-comment">/**
   * Ref used to hook into the animation
   */</span>
  <span class="hljs-attr">animationRef</span>: PropTypes.object,
  <span class="hljs-comment">/**
   * Pass custom styles for a particular color tile
   */</span>
  <span class="hljs-attr">getCustomTileStyle</span>: PropTypes.func,
  <span class="hljs-comment">/**
   * Render prop to render the color tile
   */</span>
  <span class="hljs-attr">renderTileBy</span>: PropTypes.func
};

ColorPaletteList.defaultProps = {
  <span class="hljs-attr">direction</span>: COL_DIRECTION,
  <span class="hljs-attr">onColorClick</span>: <span class="hljs-function">() =&gt;</span> {},
  <span class="hljs-attr">onColorDoubleClick</span>: <span class="hljs-function">() =&gt;</span> {},
  <span class="hljs-attr">getCustomTileStyle</span>: <span class="hljs-function">() =&gt;</span> ({}),
  <span class="hljs-attr">renderTileBy</span>: <span class="hljs-function">(<span class="hljs-params">color, className, onClick, hideName, hideHex</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ColorTile</span>
      <span class="hljs-attr">key</span>=<span class="hljs-string">{color.name}</span>
      <span class="hljs-attr">color</span>=<span class="hljs-string">{color.color}</span>
      <span class="hljs-attr">name</span>=<span class="hljs-string">{color.name}</span>
      <span class="hljs-attr">size</span>=<span class="hljs-string">{color.isMain</span> ? "<span class="hljs-attr">lg</span>" <span class="hljs-attr">:</span> "<span class="hljs-attr">md</span>"}
      <span class="hljs-attr">className</span>=<span class="hljs-string">{className}</span>
      <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onClick}</span>
      <span class="hljs-attr">hideName</span>=<span class="hljs-string">{hideName}</span>
      <span class="hljs-attr">hideHex</span>=<span class="hljs-string">{hideHex}</span>
    /&gt;</span></span>
  )
};
</code></pre>
<h4 id="heading-notes-on-the-implementation-2">Notes on the implementation</h4>
<ol>
<li>On line 34–40 you can see our implementation of React Spring using <code>useTrail</code> . You can read more about trails <a target="_blank" href="https://www.react-spring.io/docs/hooks/use-trail">here</a>. We animate the margin on the Color Tile container and depending on whether the list is column aligned or row aligned this could be the margin on the right or bottom.</li>
<li>On line 39 you can see that we pass a ref to our animation. This is so that we can pass a ref to our Color List to delay the animation. This would be useful is we wanted to trigger a specific sequence of animations from a parent component.</li>
</ol>
<pre><code class="lang-css"><span class="hljs-selector-class">.containerCol</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
}

<span class="hljs-selector-class">.containerRow</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: row;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">flex-wrap</span>: wrap;
}
</code></pre>
<h2 id="heading-color-pair">Color Pair</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/07/Accessible-Pair--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Color Pair Designs</em></p>
<p>The Color Pair component takes two colors and displays them side by side along with some accessibility information. The idea is that a developer or designer would pair colors to ensure they work together when used as a background/foreground combination.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> AccessiblePair = <span class="hljs-function">(<span class="hljs-params">{
  background,
  foreground,
  hideCloseBtn,
  onCloseBtnClick,
  closeBtnIcon,
  ...otherProps
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> title = <span class="hljs-string">`<span class="hljs-subst">${background.name}</span>/<span class="hljs-subst">${foreground.name}</span>`</span>;

  <span class="hljs-keyword">const</span> bgTileStyle = {
    <span class="hljs-string">"--tile-color"</span>: background.color
  };

  <span class="hljs-keyword">const</span> fgTileStyle = {
    <span class="hljs-string">"--tile-color"</span>: foreground.color
  };

  <span class="hljs-keyword">const</span> tileContainerClass = cx(styles.tileContainer, <span class="hljs-string">"margin-right--sm"</span>);
  <span class="hljs-keyword">const</span> titleContainerClass = cx(
    styles.titleContainer,
    <span class="hljs-string">"margin-bottom--xxs"</span>,
    <span class="hljs-string">"text--colors-grey-lighten-30"</span>
  );

  <span class="hljs-keyword">const</span> isAAPass = tinycolor.isReadable(background.color, foreground.color, {
    <span class="hljs-attr">level</span>: <span class="hljs-string">"AA"</span>,
    <span class="hljs-attr">size</span>: <span class="hljs-string">"small"</span>
  });
  <span class="hljs-keyword">const</span> isAAAPass = tinycolor.isReadable(background.color, foreground.color, {
    <span class="hljs-attr">level</span>: <span class="hljs-string">"AAA"</span>,
    <span class="hljs-attr">size</span>: <span class="hljs-string">"small"</span>
  });

  <span class="hljs-keyword">const</span> aaDisplayText = <span class="hljs-string">"WCAG AA"</span>;
  <span class="hljs-keyword">const</span> aaaDisplayText = <span class="hljs-string">"WCAG AAA"</span>;
  <span class="hljs-keyword">const</span> aaPillType = isAAPass ? <span class="hljs-string">"success"</span> : <span class="hljs-string">"error"</span>;
  <span class="hljs-keyword">const</span> aaaPillType = isAAAPass ? <span class="hljs-string">"success"</span> : <span class="hljs-string">"error"</span>;

  <span class="hljs-keyword">const</span> examplePillStyle = {
    <span class="hljs-string">"--pill-background"</span>: background.color,
    <span class="hljs-string">"--pill-color"</span>: foreground.color
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> {<span class="hljs-attr">...otherProps</span>}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{titleContainerClass}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.title}</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span>
        {!hideCloseBtn &amp;&amp; (
          <span class="hljs-tag">&lt;<span class="hljs-name">FontAwesomeIcon</span> <span class="hljs-attr">icon</span>=<span class="hljs-string">{closeBtnIcon}</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onCloseBtnClick}</span> /&gt;</span>
        )}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.mainContent}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{tileContainerClass}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{bgTileStyle}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.tile}</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{fgTileStyle}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.tile}</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.pillContainer}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Pill</span> <span class="hljs-attr">type</span>=<span class="hljs-string">{aaPillType}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"margin-bottom--xxs"</span>&gt;</span>
            {aaDisplayText}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Pill</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Pill</span> <span class="hljs-attr">type</span>=<span class="hljs-string">{aaaPillType}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"margin-bottom--xxs"</span>&gt;</span>
            {aaaDisplayText}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Pill</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Pill</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{examplePillStyle}</span>&gt;</span>This is how text will look<span class="hljs-tag">&lt;/<span class="hljs-name">Pill</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

AccessiblePair.propTypes = {
  <span class="hljs-comment">/**
   * The background color
   */</span>
  <span class="hljs-attr">background</span>: colorShape.isRequired,
  <span class="hljs-comment">/**
   * The foreground color
   */</span>
  <span class="hljs-attr">foreground</span>: colorShape.isRequired,
  <span class="hljs-comment">/**
   * Set to true to hide the close button
   */</span>
  <span class="hljs-attr">hideCloseBtn</span>: PropTypes.bool,
  <span class="hljs-comment">/**
   * Callback for when the close button is clicked
   */</span>
  <span class="hljs-attr">onCloseBtnClick</span>: PropTypes.func,
  <span class="hljs-comment">/**
   * FontAwesome icon to use for the close button
   */</span>
  <span class="hljs-attr">closeBtnIcon</span>: PropTypes.string
};

AccessiblePair.defaultProps = {
  <span class="hljs-attr">hideCloseBtn</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">onCloseBtnClick</span>: <span class="hljs-function">() =&gt;</span> {},
  <span class="hljs-attr">closeBtnIcon</span>: <span class="hljs-string">"times"</span>
};
</code></pre>
<h4 id="heading-notes-on-the-implementation-3">Notes on the implementation</h4>
<p>As mentioned, our Color Pair component takes a background and foreground color, and on line 26–33 you can see where we use Tinycolor to determine the accessibility of the color pair.</p>
<p>We use a simple Pill component to display the result with the type of the Pill being determined by the result. I haven’t shown the source for the Pill here, but it’s a pretty standard component that you would find in any component library (Bootstrap, Material, etc).</p>
<p>You can learn more about accessibility and WCAG <a target="_blank" href="https://www.w3.org/WAI/standards-guidelines/wcag/">here</a>.</p>
<h2 id="heading-conclusion-and-source-code">Conclusion and source code</h2>
<p>I hope you have learned something from this walkthrough. I highly recommend looking into the libraries I have mentioned here in your next project. In particular, my application would have taken much longer to create without the excellent Tinycolor package.</p>
<blockquote>
<p><em>Source code for the full application can be found <a target="_blank" href="https://github.com/stephan-mclean/project-color">here</a>.</em></p>
<p><em>A Storybook instance with all of the components can be found <a target="_blank" href="https://rainbo-components.netlify.com/">here</a>.</em></p>
</blockquote>
<p>If you have any feedback on the designs, code, or in general, I would love to hear it.</p>
<p>Thank you very much for reading my article!</p>
<p><em>Originally published <a target="_blank" href="https://medium.com/better-programming/building-colorful-springy-components-using-react-spring-and-tinycolor-1086c6594203">here</a>.</em> </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to improve your UI/UX design skills as a developer ]]>
                </title>
                <description>
                    <![CDATA[ By Stephen McLean If you had asked me four years ago, when I became a CS graduate, what kind of career path I saw myself following, I probably would have told you back-end Java development or something similar. I was never creative, in the paint meet... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-improve-your-ui-ux-design-skills-as-a-developer-1fd96a49d807/</link>
                <guid isPermaLink="false">66d4614e230dff0166905881</guid>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 24 Apr 2019 22:18:19 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*pVsQ9Re0clHQGDWg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Stephen McLean</p>
<p>If you had asked me four years ago, when I became a CS graduate, what kind of career path I saw myself following, I probably would have told you back-end Java development or something similar. I was never creative, in the paint meets canvas kind of way, so I didn’t really consider a career path involving front-end development and design.</p>
<p>As we all know, things change. Over the course of my career, I have become more and more interested in UI development and design. I have been lucky enough in my job to have gained exposure to front-end development and to have been allowed to invest time in improving the skills necessary to be a front-end developer.</p>
<p>Over the past 12 months, I have been striving to improve my understanding of UI/UX design, both because of personal interest and to allow me to be more effective when working with designers.</p>
<p>In this post, I would like to share the lessons I have learned, the resources I have gathered, and the mistakes I have made in the hopes that other developers will be able to learn from my journey.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ul>
<li><a class="post-section-overview" href="#fb0b">It’s not just talent</a></li>
<li><a class="post-section-overview" href="#bb43">Look, think, steal</a></li>
<li><a class="post-section-overview" href="#759a">Learn the theory</a></li>
<li><a class="post-section-overview" href="#1373">Build something</a></li>
<li><a class="post-section-overview" href="#7f61">Don’t give up</a></li>
<li><a class="post-section-overview" href="#4562">Resources</a></li>
<li><a class="post-section-overview" href="#d161">Conclusion</a></li>
</ul>
<h3 id="heading-its-not-just-talent">It’s not just talent</h3>
<p>This one seems obvious to me now, but there was a time when I thought that designers were wizards that were born with the ability to create amazing looking apps, and websites.</p>
<p>It turns out that they’re not. They have just worked hard to perfect their craft. In the same way that learning to code comes easier to some people, there are people who will have a natural talent for design, but talent doesn’t mean much without hard work.</p>
<p>Design is something that can be learned. Don’t make the mistake I did and write yourself off because you’re not creative in the traditional sense. Solving programming problems takes creativity; think about solving design challenges in the same way.</p>
<h3 id="heading-look-think-steal">Look, think, steal</h3>
<p>In the same way that reading good code will help you become a better developer, learning from what others have created will help you become a better designer.</p>
<p>The next time you visit a website or use an app, <em>look</em> at it and really <em>think</em> about why it looks and behaves the way it does. Why are the elements are placed where they are? Why is that button a particular color? Why do you have to perform actions in a certain order?</p>
<p>Take Medium’s applause button for example. Why didn’t they just use a “like” button like every other social media website? In my opinion, it was a clever design decision not to. Instead, they are able to reinforce the idea of community that drives the site by carefully designing an interaction. Giving an article or response fifty claps takes time for a user to do, but it helps them to really connect with the content they are viewing and the person who created it.</p>
<p>Sites like <a target="_blank" href="https://www.awwwards.com/">Awwwards</a> and <a target="_blank" href="https://dribbble.com/">Dribbble</a> have proven invaluable to me in the last year. Many of the designs I have created have taken <em>liberal</em> inspiration from the creations of other great designers.</p>
<h3 id="heading-learn-the-theory">Learn the theory</h3>
<p>When I first started putting together designs of my own, I couldn’t figure out why they looked and behaved so poorly. The flows were awkward, the colors mismatched, and the layouts were inconsistent.</p>
<p>I thought I could just jump straight in and use my development knowledge along with my basic knowledge of how sites <em>should</em> work, as a user, and it would work out fine.</p>
<p>I was very, very wrong. I ended up creating designs from a developers point of view, instead of using design theory as a base.</p>
<p>Developers know how a site <em>works</em>, but designers know how a site <em>behaves and feels.</em> There is a big gap that you can only fill by gaining a foundation in design knowledge.</p>
<p>To gain a basic understanding of design theory, I mostly used Medium and Udemy. You can find links to the <a class="post-section-overview" href="#4562">resources I used</a> in the section below.</p>
<h3 id="heading-build-something">Build something</h3>
<p>Any developer or CS professor will tell you that the best way to become a better programmer is to write code. The same principle applies to design.</p>
<p>It doesn’t matter what you design, as long as you learn from it. Treat it as a real project: Think about the users. Create wireframes, mockups, and prototypes. Iterate on the original design to improve it. You can use sites like <a target="_blank" href="https://www.reddit.com/r/design_critiques/">Reddit</a> to get feedback on what you create.</p>
<p>You can even pair it with improving your development skills. Most of my recent side projects have been motivated by a joint desire to improve both my web development and design skills. After you design your project, you can develop it and see both sides of the coin.</p>
<p>Here are some ideas to get you started:</p>
<ul>
<li>Design an <em>interaction.</em> Use Medium’s applause button for inspiration.</li>
<li>Design an app for your favorite charity. Think about the different kinds of users: potential, infrequent, and regular patrons.</li>
<li>Design your CV. Think about the colors you use and what the mean. Think about how your CV will be <em>used.</em> Will it just be viewed on a screen, or will it be printed out? How does that influence the design?</li>
<li>Redesign an existing website. It could be your local transport provider or a global brand. Compare your design with the original and think about the differences from a user’s perspective.</li>
<li>Design something physical, such as a new method of transport or maybe an alternative to something simple like a fork or chair. I have found thinking about the <a target="_blank" href="https://www.amazon.com/Design-Everyday-Things-Donald-Norman/dp/0465067107/ref=tmm_pap_swatch_0?_encoding=UTF8&amp;qid=&amp;sr=">design of everyday things</a> to be a really useful way of getting in the mindset to design something intuitive.</li>
</ul>
<h3 id="heading-dont-give-up">Don’t give up</h3>
<p>When I look back on what I created a year ago, it’s hard not to wince. But everyone starts somewhere. Seeing the progression in what you create will be worth it. As long as you are learning from what you’re doing then your time is being well spent.</p>
<p>It might help to keep track of what you have learned at a regular interval. Every month I look back at some of the things I have worked on and try to take as much as I can from the experience. Even if it’s only to recognize some small piece of information you picked up from reading an article, it’s still progress.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/4WVxeDLz1qVdJ2-i4avjX67sSzR9H8eTelas" alt="Image" width="800" height="473" loading="lazy">
<em>Some designs I have created from oldest (left) to newest (right)</em></p>
<h3 id="heading-resources">Resources</h3>
<p>Below is a small collection of my favorite tools, articles, and courses. You can find <em>many</em> more that I haven’t listed <a target="_blank" href="https://github.com/gztchan/awesome-design">here</a>, and <a target="_blank" href="https://github.com/LisaDziuba/Awesome-Design-Tools">here</a>.</p>
<h4 id="heading-tools">Tools</h4>
<p><a target="_blank" href="https://www.figma.com/">Figma</a> — Design and prototyping with collaboration.</p>
<p><a target="_blank" href="https://www.framer.com/">FramerX</a> — Similar to Figma, but with added React, and discoverable components.</p>
<p><a target="_blank" href="https://coolors.co/">Coolors</a> — Discover and generate color palletes.</p>
<p><a target="_blank" href="https://webaim.org/resources/contrastchecker/">WebAIM Contrast Checker</a> — Make sure your colors are accessible.</p>
<p><a target="_blank" href="https://archetypeapp.com/#">Archetype</a> — Typography system editor and generator.</p>
<h4 id="heading-articles">Articles</h4>
<p><a target="_blank" href="https://medium.com/refactoring-ui/7-practical-tips-for-cheating-at-design-40c736799886">7 Practical Tips for Cheating at Design</a></p>
<p><a target="_blank" href="https://medium.com/sketch-app-sources/design-cheatsheet-274384775da9">10 cheat codes for designing User Interfaces</a></p>
<p><a target="_blank" href="https://uxplanet.org/10-small-design-mistakes-we-still-make-1cd5f60bc708">10 Small Design Mistakes We Still Make</a></p>
<p><a target="_blank" href="https://uxdesign.cc/design-better-forms-96fadca0f49c">Design Better Forms</a></p>
<p><a target="_blank" href="https://uxplanet.org/a-complete-list-of-ux-deliverables-d62ccf1de434">A Complete List Of UX Deliverables</a></p>
<p><a target="_blank" href="https://uxplanet.org/the-psychology-principles-every-ui-ux-designer-needs-to-know-24116fd65778">The Psychology Principles Every UI/UX Designer Needs to Know</a></p>
<p><a target="_blank" href="https://blog.prototypr.io/how-to-use-colors-in-ui-design-16406ec06753">How to use colors in UI Design</a></p>
<p><a target="_blank" href="https://uxplanet.org/16-quotes-you-need-to-read-as-ux-designer-e47f982e312c">16 Quotes You Need to Read as UX Designer</a></p>
<p><a target="_blank" href="https://blog.prototypr.io/product-design-principles-in-a-single-card-2f6023419a87">Product Design Principles in a Single Card</a></p>
<h4 id="heading-courses">Courses</h4>
<p><a target="_blank" href="https://www.udemy.com/course/user-experience-design-fundamentals/">User Experience Design Fundamentals</a> — Udemy</p>
<p><a target="_blank" href="https://www.udemy.com/course/the-complete-app-design-course-ux-and-ui-design/">The Complete App Design Course — UX, UI and Design Thinking</a> — Udemy</p>
<p><a target="_blank" href="https://www.uxtraining.com/">UXTraining.com</a></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>I hope you have been able to take something from my journey. If you have design tips or resources that have helped you learn, I would love to hear them in the responses.</p>
<p>Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The CSS Handbook: A Handy Guide to CSS for Developers ]]>
                </title>
                <description>
                    <![CDATA[ I wrote this article to help you quickly learn CSS and get familiar with the advanced CSS topics. CSS is often quickly dismissed as an easy thing to learn by developers, or one thing you just pick up when you need to quickly style a page or app. Due ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/</link>
                <guid isPermaLink="false">66bb5a9b965d5c9ed5487bb0</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Flavio Copes ]]>
                </dc:creator>
                <pubDate>Wed, 24 Apr 2019 15:51:53 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*aeXtrs9UI4WniMd1miDIDw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I wrote this article to help you quickly learn CSS and get familiar with the advanced CSS topics.</p>
<p>CSS is often quickly dismissed as an easy thing to learn by developers, or one thing you just pick up when you need to quickly style a page or app. Due to this reason, it’s often learned on-the-fly, or we learn things in isolation right when we have to use them. This can be a huge source of frustration when we find that the tool does not simply do what we want.</p>
<p>This article will help you get up to speed with CSS and get an overview of the main modern features you can use to style your pages and apps.</p>
<p>I hope to help you get comfortable with CSS and get you quickly up to speed with using this awesome tool that lets you create stunning designs on the Web.</p>
<p><strong><a target="_blank" href="https://flaviocopes.com/page/css-handbook">Click here to get a PDF / ePub / Mobi version of this post to read offline</a></strong></p>
<p>CSS, a shorthand for Cascading Style Sheets, is one of the main building blocks of the Web. Its history goes back to the 90’s, and along with HTML it has changed a lot since its humble beginnings.</p>
<p>As I’ve been creating websites since before CSS existed, I have seen its evolution.</p>
<p>CSS is an amazing tool, and in the last few years it has grown a lot, introducing many fantastic features like CSS Grid, Flexbox and CSS Custom Properties.</p>
<p>This handbook is aimed at a vast audience.</p>
<p>First, the beginner. I explain CSS from zero in a succinct but comprehensive way, so you can use this book to learn CSS from the basics.</p>
<p>Then, the professional. CSS is often considered like a secondary thing to learn, especially by JavaScript developers. They know CSS is not a real programming language, they are programmers and therefore they should not bother learning CSS the right way. I wrote this book for you, too.</p>
<p>Next, the person that knows CSS from a few years but hasn’t had the opportunity to learn the new things in it. We’ll talk extensively about the new features of CSS, the ones that are going to build the web of the next decade.</p>
<p>CSS has improved a lot in the past few years and it’s evolving fast.</p>
<p>Even if you don’t write CSS for a living, knowing how CSS works can help save you some headaches when you need to understand it from time to time, for example while tweaking a web page.</p>
<p>Thank you for getting this ebook. My goal with it is to give you a quick yet comprehensive overview of CSS.</p>
<p>Flavio</p>
<p>You can reach me via email at <a target="_blank" href="mailto:flavio@flaviocopes.com">flavio@flaviocopes.com</a>, on Twitter <a target="_blank" href="https://twitter.com/flaviocopes">@flaviocopes</a>.</p>
<p>My website is <a target="_blank" href="https://flaviocopes.com/">flaviocopes.com</a>.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#introduction-to-css">INTRODUCTION TO CSS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#a-brief-history-of-css">A BRIEF HISTORY OF CSS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#adding-css-to-an-html-page">ADDING CSS TO AN HTML PAGE</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#selectors">SELECTORS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#cascade">CASCADE</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#specificity">SPECIFICITY</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#inheritance">INHERITANCE</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#import">IMPORT</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#attribute-selectors">ATTRIBUTE SELECTORS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#pseudo-classes">PSEUDO-CLASSES</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#pseudo-elements">PSEUDO-ELEMENTS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#colors">COLORS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#units">UNITS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#url">URL</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#calc">CALC</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#backgrounds">BACKGROUNDS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#comments">COMMENTS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#custom-properties">CUSTOM PROPERTIES</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#fonts">FONTS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#typography">TYPOGRAPHY</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#box-model">BOX MODEL</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#border">BORDER</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#padding">PADDING</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#margin">MARGIN</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#box-sizing">BOX SIZING</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#display">DISPLAY</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#positioning">POSITIONING</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#floating-and-clearing">FLOATING AND CLEARING</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#z-index">Z-INDEX</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#css-grid">CSS GRID</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#flexbox">FLEXBOX</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#tables">TABLES</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#centering">CENTERING</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#lists">LISTS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#media-queries-and-responsive-design">MEDIA QUERIES AND RESPONSIVE DESIGN</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#feature-queries">FEATURE QUERIES</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#filters">FILTERS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#transforms">TRANSFORMS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#transitions">TRANSITIONS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#animations">ANIMATIONS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#normalizing-css">NORMALIZING CSS</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#error-handling">ERROR HANDLING</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#vendor-prefixes">VENDOR PREFIXES</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#css-for-print">CSS FOR PRINT</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-css-handbook-a-handy-guide-to-css-for-developers-b56695917d11/#wrapping-up">WRAPPING UP</a></li>
</ul>
<h3 id="heading-introduction-to-css">INTRODUCTION TO CSS</h3>
<p><strong>CSS</strong> (an abbreviation of <strong>Cascading Style Sheets</strong>) is the language that we use to style an HTML file, and tell the browser how should it render the elements on the page.</p>
<blockquote>
<p><em>In this book I talk exclusively about styling HTML documents, although CSS can be used to style other things too.</em></p>
</blockquote>
<p>A CSS file contains several CSS rules.</p>
<p>Each rule is composed by 2 parts:</p>
<ul>
<li>the <strong>selector</strong></li>
<li>the <strong>declaration block</strong></li>
</ul>
<p>The selector is a string that identifies one or more elements on the page, following a special syntax that we’ll soon talk about extensively.</p>
<p>The declaration block contains one or more <strong>declarations</strong>, in turn composed by a <strong>property</strong> and <strong>value</strong> pair.</p>
<p>Those are all the things we have in CSS.</p>
<p>Carefully organising properties, associating them values, and attaching those to specific elements of the page using a selector is the whole argument of this ebook.</p>
<h4 id="heading-how-does-css-look-like">How does CSS look like</h4>
<p>A CSS <strong>rule set</strong> has one part called <strong>selector</strong>, and the other part called <strong>declaration</strong>. The declaration contains various <strong>rules</strong>, each composed by a <strong>property</strong>, and a <strong>value</strong>.</p>
<p>In this example, <code>p</code> is the selector, and applies one rule which sets the value <code>20px</code> to the <code>font-size</code> property:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;
}
</code></pre>
<p>Multiple rules are stacked one after the other:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-tag">a</span> {
  <span class="hljs-attribute">color</span>: blue;
}
</code></pre>
<p>A selector can target one or more items:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span>, <span class="hljs-selector-tag">a</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;
}
</code></pre>
<p>and it can target HTML tags, like above, or HTML elements that contain a certain class attribute with <code>.my-class</code>, or HTML elements that have a specific <code>id</code> attribute with <code>#my-id</code>.</p>
<p>More advanced selectors allow you to choose items whose attribute matches a specific value, or also items which respond to pseudo-classes (more on that later)</p>
<h4 id="heading-semicolons">Semicolons</h4>
<p>Every CSS rule terminates with a semicolon. Semicolons are <strong>not</strong> optional, except after the last rule. But I suggest to always use them for consistency and to avoid errors if you add another property and forget to add the semicolon on the previous line.</p>
<h4 id="heading-formatting-and-indentation">Formatting and indentation</h4>
<p>There is no fixed rule for formatting. This CSS is valid:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span>
      {
  <span class="hljs-attribute">font-size</span>:           <span class="hljs-number">20px</span>   ;
                      }

<span class="hljs-selector-tag">a</span>{<span class="hljs-attribute">color</span>:blue;}
</code></pre>
<p>but a pain to see. Stick to some conventions, like the ones you see in the examples above: stick selectors and the closing brackets to the left, indent 2 spaces for each rule, have the opening bracket on the same line of the selector, separated by one space.</p>
<p>Correct and consistent use of spacing and indentation is a visual aid in understanding your code.</p>
<h3 id="heading-a-brief-history-of-css">A BRIEF HISTORY OF CSS</h3>
<p>Before moving on, I want to give you a brief recap of the history of CSS.</p>
<p>CSS was grown out of the necessity of styling web pages. Before CSS was introduced, people wanted a way to style their web pages, which looked all very similar and “academic” back in the day. You couldn’t do much in terms of personalisation.</p>
<p>HTML 3.2 introduced the option of defining colors inline as HTML element attributes, and presentational tags like <code>center</code> and <code>font</code>, but that escalated quickly into a far from ideal situation.</p>
<p>CSS let us move everything presentation-related from the HTML to the CSS, so that HTML could get back being the format that defines the structure of the document, rather than how things should look in the browser.</p>
<p>CSS is continuously evolving, and CSS you used 5 years ago might just be outdated, as new idiomatic CSS techniques emerged and browsers changed.</p>
<p>It’s hard to imagine the times when CSS was born and how different the web was.</p>
<p>At the time, we had several competing browsers, the main ones being Internet Explorer or Netscape Navigator.</p>
<p>Pages were styled by using HTML, with special presentational tags like <code>bold</code> and special attributes, most of which are now deprecated.</p>
<p>This meant you had a limited amount of customisation opportunities.</p>
<p>The bulk of the styling decisions were left to the browser.</p>
<p>Also, you built a site specifically for one of them, because each one introduced different non-standard tags to give more power and opportunities.</p>
<p>Soon people realised the need for a way to style pages, in a way that would work across all browsers.</p>
<p>After the initial idea proposed in 1994, CSS got its first release in 1996, when the CSS Level 1 (“CSS 1”) recommendation was published.</p>
<p>CSS Level 2 (“CSS 2”) got published in 1998.</p>
<p>Since then, work began on CSS Level 3. The CSS Working Group decided to split every feature and work on it separately, in modules.</p>
<p>Browsers weren’t especially fast at implementing CSS. We had to wait until 2002 to have the first browser implement the full CSS specification: IE for Mac, as nicely described in this CSS Tricks post: <a target="_blank" href="https://css-tricks.com/look-back-history-css/">https://css-tricks.com/look-back-history-css/</a></p>
<p>Internet Explorer implemented the box model incorrectly right from the start, which led to years of pain trying to have the same style applied consistently across browsers. We had to use various tricks and hacks to make browsers render things as we wanted.</p>
<p>Today things are much, much better. We can just use the CSS standards without thinking about quirks, most of the time, and CSS has never been more powerful.</p>
<p>We don’t have official release numbers for CSS any more now, but the CSS Working Group releases a “snapshot” of the modules that are currently considered stable and ready to be included in browsers. This is the latest snapshot, from 2018: <a target="_blank" href="https://www.w3.org/TR/css-2018/">https://www.w3.org/TR/css-2018/</a></p>
<p>CSS Level 2 is still the base for the CSS we write today, and we have many more features built on top of it.</p>
<h3 id="heading-adding-css-to-an-html-page">ADDING CSS TO AN HTML PAGE</h3>
<p>CSS is attached to an HTML page in different ways.</p>
<h4 id="heading-1-using-the-link-tag">1: Using the <code>link</code> tag</h4>
<p>The <code>link</code> tag is the way to include a CSS file. This is the preferred way to use CSS as it's intended to be used: one CSS file is included by all the pages of your site, and changing one line on that file affects the presentation of all the pages in the site.</p>
<p>To use this method, you add a <code>link</code> tag with the <code>href</code> attribute pointing to the CSS file you want to include. You add it inside the <code>head</code> tag of the site (not inside the <code>body</code> tag):</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"myfile.css"</span>&gt;</span>
</code></pre>
<p>The <code>rel</code> and <code>type</code> attributes are required too, as they tell the browser which kind of file we are linking to.</p>
<h4 id="heading-2-using-the-style-tag">2: using the <code>style</code> tag</h4>
<p>Instead of using the <code>link</code> tag to point to separate stylesheet containing our CSS, we can add the CSS directly inside a <code>style</code> tag. This is the syntax:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
..<span class="hljs-selector-class">.our</span> <span class="hljs-selector-tag">CSS</span>...
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Using this method we can avoid creating a separate CSS file. I find this is a good way to experiment before “formalising” CSS to a separate file, or to add a special line of CSS just to a file.</p>
<h4 id="heading-3-inline-styles">3: inline styles</h4>
<p>Inline styles are the third way to add CSS to a page. We can add a <code>style</code> attribute to any HTML tag, and add CSS into it.</p>
<pre><code>&lt;div style=<span class="hljs-string">""</span>&gt;...&lt;/div&gt;
</code></pre><p>Example:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-color: yellow"</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<h3 id="heading-selectors">SELECTORS</h3>
<p>A selector allows us to associate one or more declarations to one or more elements on the page.</p>
<h4 id="heading-basic-selectors">Basic selectors</h4>
<p>Suppose we have a <code>p</code> element on the page, and we want to display the words into it using the yellow color.</p>
<p>We can <strong>target</strong> that element using this selector <code>p</code>, which targets all the element using the <code>p</code> tag in the page. A simple CSS rule to achieve what we want is:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>Every HTML tag has a corresponding selector, for example: <code>div</code>, <code>span</code>, <code>img</code>.</p>
<p>If a selector matches multiple elements, all the elements in the page will be affected by the change.</p>
<p>HTML elements have 2 attributes which are very commonly used within CSS to associate styling to a specific element on the page: <code>class</code> and <code>id</code>.</p>
<p>There is one big difference between those two: inside an HTML document you can repeat the same <code>class</code> value across multiple elements, but you can only use an <code>id</code> once. As a corollary, using classes you can select an element with 2 or more specific class names, something not possible using ids.</p>
<p>Classes are identified using the <code>.</code> symbol, while ids using the <code>#</code> symbol.</p>
<p>Example using a class:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">p</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">dog-name</span>"&gt;
  <span class="hljs-selector-tag">Roger</span>
&lt;/<span class="hljs-selector-tag">p</span>&gt;

<span class="hljs-selector-class">.dog-name</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>Example using an id:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">p</span> <span class="hljs-selector-tag">id</span>="<span class="hljs-selector-tag">dog-name</span>"&gt;
  <span class="hljs-selector-tag">Roger</span>
&lt;/<span class="hljs-selector-tag">p</span>&gt;

<span class="hljs-selector-id">#dog-name</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<h4 id="heading-combining-selectors">Combining selectors</h4>
<p>So far we’ve seen how to target an element, a class or an id. Let’s introduce more powerful selectors.</p>
<h4 id="heading-targeting-an-element-with-a-class-or-id">Targeting an element with a class or id</h4>
<p>You can target a specific element that has a class, or id, attached.</p>
<p>Example using a class:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">p</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">dog-name</span>"&gt;
  <span class="hljs-selector-tag">Roger</span>
&lt;/<span class="hljs-selector-tag">p</span>&gt;

<span class="hljs-selector-tag">p</span><span class="hljs-selector-class">.dog-name</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>Example using an id:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">p</span> <span class="hljs-selector-tag">id</span>="<span class="hljs-selector-tag">dog-name</span>"&gt;
  <span class="hljs-selector-tag">Roger</span>
&lt;/<span class="hljs-selector-tag">p</span>&gt;

<span class="hljs-selector-tag">p</span><span class="hljs-selector-id">#dog-name</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>Why would you want to do that, if the class or id already provides a way to target that element? You might have to do that to have more specificity. We’ll see what that means later.</p>
<h4 id="heading-targeting-multiple-classes">Targeting multiple classes</h4>
<p>You can target an element with a specific class using <code>.class-name</code>, as you saw previously. You can target an element with 2 (or more) classes by combining the class names separated with a dot, without spaces.</p>
<p>Example:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">p</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">dog-name</span> <span class="hljs-selector-tag">roger</span>"&gt;
  <span class="hljs-selector-tag">Roger</span>
&lt;/<span class="hljs-selector-tag">p</span>&gt;

<span class="hljs-selector-class">.dog-name</span><span class="hljs-selector-class">.roger</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<h4 id="heading-combining-classes-and-ids">Combining classes and ids</h4>
<p>In the same way, you can combine a class and an id.</p>
<p>Example:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">p</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">dog-name</span>" <span class="hljs-selector-tag">id</span>="<span class="hljs-selector-tag">roger</span>"&gt;
  <span class="hljs-selector-tag">Roger</span>
&lt;/<span class="hljs-selector-tag">p</span>&gt;

<span class="hljs-selector-class">.dog-name</span><span class="hljs-selector-id">#roger</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<h4 id="heading-grouping-selectors">Grouping selectors</h4>
<p>You can combine selectors to apply the same declarations to multiple selectors. To do so, you separate them with a comma.</p>
<p>Example:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">p</span>&gt;
  <span class="hljs-selector-tag">My</span> <span class="hljs-selector-tag">dog</span> <span class="hljs-selector-tag">name</span> <span class="hljs-selector-tag">is</span>:
&lt;/<span class="hljs-selector-tag">p</span>&gt;
&lt;<span class="hljs-selector-tag">span</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">dog-name</span>"&gt;
  <span class="hljs-selector-tag">Roger</span>
&lt;/<span class="hljs-selector-tag">span</span>&gt;

<span class="hljs-selector-tag">p</span>, <span class="hljs-selector-class">.dog-name</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>You can add spaces in those declarations to make them more clear:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span>,
<span class="hljs-selector-class">.dog-name</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<h4 id="heading-follow-the-document-tree-with-selectors">Follow the document tree with selectors</h4>
<p>We’ve seen how to target an element in the page by using a tag name, a class or an id.</p>
<p>You can create a more specific selector by combining multiple items to follow the document tree structure. For example, if you have a <code>span</code> tag nested inside a <code>p</code> tag, you can target that one without applying the style to a <code>span</code> tag not included in a <code>p</code> tag:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">span</span>&gt;
  <span class="hljs-selector-tag">Hello</span>!
&lt;/<span class="hljs-selector-tag">span</span>&gt;
&lt;<span class="hljs-selector-tag">p</span>&gt;
  <span class="hljs-selector-tag">My</span> <span class="hljs-selector-tag">dog</span> <span class="hljs-selector-tag">name</span> <span class="hljs-selector-tag">is</span>:
  &lt;<span class="hljs-selector-tag">span</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">dog-name</span>"&gt;
    <span class="hljs-selector-tag">Roger</span>
  &lt;/<span class="hljs-selector-tag">span</span>&gt;
&lt;/<span class="hljs-selector-tag">p</span>&gt;

<span class="hljs-selector-tag">p</span> <span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>See how we used a space between the two tokens <code>p</code> and <code>span</code>.</p>
<p>This works even if the element on the right is multiple levels deep.</p>
<p>To make the dependency strict on the first level, you can use the <code>&gt;</code> symbol between the two tokens:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> &gt; <span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>In this case, if a <code>span</code> is not a first children of the <code>p</code> element, it's not going to have the new color applied.</p>
<p>Direct children will have the style applied:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
    This is yellow
  <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
      This is not yellow
    <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>Adjacent sibling selectors let us style an element only if preceded by a specific element. We do so using the <code>+</code> operator:</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> + <span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>This will assign the color yellow to all span elements preceded by a <code>p</code> element:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is a paragraph<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>This is a yellow span<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
</code></pre>
<p>We have a lot more selectors we can use:</p>
<ul>
<li>attribute selectors</li>
<li>pseudo class selectors</li>
<li>pseudo element selectors</li>
</ul>
<p>We’ll find all about them in the next sections.</p>
<h3 id="heading-cascade">CASCADE</h3>
<p>Cascade is a fundamental concept of CSS. After all, it’s in the name itself, the first C of CSS — Cascading Style Sheets — it must be an important thing.</p>
<p>What does it mean?</p>
<p>Cascade is the process, or algorithm, that determines the properties applied to each element on the page. Trying to converge from a list of CSS rules that are defined in various places.</p>
<p>It does so taking in consideration:</p>
<ul>
<li>specificity</li>
<li>importance</li>
<li>inheritance</li>
<li>order in the file</li>
</ul>
<p>It also takes care of resolving conflicts.</p>
<p>Two or more competing CSS rules for the same property applied to the same element need to be elaborated according to the CSS spec, to determine which one needs to be applied.</p>
<p>Even if you just have one CSS file loaded by your page, there is other CSS that is going to be part of the process. We have the browser (user agent) CSS. Browsers come with a default set of rules, all different between browsers.</p>
<p>Then your CSS comes into play.</p>
<p>Then the browser applies any user stylesheet, which might also be applied by browser extensions.</p>
<p>All those rules come into play while rendering the page.</p>
<p>We’ll now see the concepts of specificity and inheritance.</p>
<h3 id="heading-specificity">SPECIFICITY</h3>
<p>What happens when an element is targeted by multiple rules, with different selectors, that affect the same property?</p>
<p>For example, let’s talk about this element:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dog-name"</span>&gt;</span>
  Roger
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>We can have</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.dog-name</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>and another rule that targets <code>p</code>, which sets the color to another value:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">color</span>: red;
}
</code></pre>
<p>And another rule that targets <code>p.dog-name</code>. Which rule is going to take precedence over the others, and why?</p>
<p>Enter specificity. <strong>The more specific rule will win</strong>. If two or more rules have the <strong>same specificity, the one that appears last wins</strong>.</p>
<p>Sometimes what is more specific in practice is a bit confusing to beginners. I would say it’s also confusing to experts that do not look at those rules that frequently, or simply overlook them.</p>
<h4 id="heading-how-to-calculate-specificity">How to calculate specificity</h4>
<p>Specificity is calculated using a convention.</p>
<p>We have 4 slots, and each one of them starts at 0: <code>0 0 0 0</code>. The slot at the left is the most important, and the rightmost one is the least important.</p>
<p>Like it works for numbers in the decimal system: <code>1 0 0 0</code> is higher than <code>0 1 0 0</code>.</p>
<h4 id="heading-slot-1">Slot 1</h4>
<p>The first slot, the rightmost one, is the least important.</p>
<p>We increase this value when we have an <strong>element selector</strong>. An element is a tag name. If you have more than one element selector in the rule, you increment accordingly the value stored in this slot.</p>
<p>Examples:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {}                    <span class="hljs-comment">/* 0 0 0 1 */</span>
<span class="hljs-selector-tag">span</span> {}                 <span class="hljs-comment">/* 0 0 0 1 */</span>
<span class="hljs-selector-tag">p</span> <span class="hljs-selector-tag">span</span> {}               <span class="hljs-comment">/* 0 0 0 2 */</span>
<span class="hljs-selector-tag">p</span> &gt; <span class="hljs-selector-tag">span</span> {}             <span class="hljs-comment">/* 0 0 0 2 */</span>
<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">p</span> &gt; <span class="hljs-selector-tag">span</span> {}         <span class="hljs-comment">/* 0 0 0 3 */</span>
</code></pre>
<h4 id="heading-slot-2">Slot 2</h4>
<p>The second slot is incremented by 3 things:</p>
<ul>
<li>class selectors</li>
<li>pseudo-class selectors</li>
<li>attribute selectors</li>
</ul>
<p>Every time a rule meets one of those, we increment the value of the second column from the right.</p>
<p>Examples:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.name</span> {}                 <span class="hljs-comment">/* 0 0 1 0 */</span>
<span class="hljs-selector-class">.users</span> <span class="hljs-selector-class">.name</span> {}          <span class="hljs-comment">/* 0 0 2 0 */</span>
<span class="hljs-selector-attr">[href$=<span class="hljs-string">'.pdf'</span>]</span> {}        <span class="hljs-comment">/* 0 0 1 0 */</span>
<span class="hljs-selector-pseudo">:hover</span> {}                <span class="hljs-comment">/* 0 0 1 0 */</span>
</code></pre>
<p>Of course slot 2 selectors can be combined with slot 1 selectors:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> <span class="hljs-selector-class">.name</span> {}             <span class="hljs-comment">/* 0 0 1 1 */</span>
<span class="hljs-selector-tag">a</span><span class="hljs-selector-attr">[href$=<span class="hljs-string">'.pdf'</span>]</span> {}       <span class="hljs-comment">/* 0 0 1 1 */</span>
<span class="hljs-selector-class">.pictures</span> <span class="hljs-selector-tag">img</span><span class="hljs-selector-pseudo">:hover</span> {}   <span class="hljs-comment">/* 0 0 2 1 */</span>
</code></pre>
<p>One nice trick with classes is that you can repeat the same class and increase the specificity. For example:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.name</span> {}              <span class="hljs-comment">/* 0 0 1 0 */</span>
<span class="hljs-selector-class">.name</span><span class="hljs-selector-class">.name</span> {}         <span class="hljs-comment">/* 0 0 2 0 */</span>
<span class="hljs-selector-class">.name</span><span class="hljs-selector-class">.name</span><span class="hljs-selector-class">.name</span> {}    <span class="hljs-comment">/* 0 0 3 0 */</span>
</code></pre>
<h4 id="heading-slot-3">Slot 3</h4>
<p>Slot 3 holds the most important thing that can affect your CSS specificity in a CSS file: the <code>id</code>.</p>
<p>Every element can have an <code>id</code> attribute assigned, and we can use that in our stylesheet to target the element.</p>
<p>Examples:</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#name</span> {}                    <span class="hljs-comment">/* 0 1 0 0 */</span>
<span class="hljs-selector-class">.user</span> <span class="hljs-selector-id">#name</span> {}              <span class="hljs-comment">/* 0 1 1 0 */</span>
<span class="hljs-selector-id">#name</span> <span class="hljs-selector-tag">span</span> {}               <span class="hljs-comment">/* 0 1 0 1 */</span>
</code></pre>
<h4 id="heading-slot-4">Slot 4</h4>
<p>Slot 4 is affected by inline styles. Any inline style will have precedence over any rule defined in an external CSS file, or inside the <code>style</code> tag in the page header.</p>
<p>Example:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: red"</span>&gt;</span>Test<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> /* 1 0 0 0 */
</code></pre>
<p>Even if any other rule in the CSS defines the color, this inline style rule is going to be applied. Except for one case — if <code>!important</code> is used, which fills the slot 5.</p>
<h4 id="heading-importance">Importance</h4>
<p>Specificity does not matter if a rule ends with <code>!important</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span><span class="hljs-meta">!important</span>;
}
</code></pre>
<p>That rule will take precedence over any rule with more specificity</p>
<p>Adding <code>!important</code> in a CSS rule is going to make that rule more important than any other rule, according to the specificity rules. The only way another rule can take precedence is to have <code>!important</code> as well, and have higher specificity in the other less important slots.</p>
<h4 id="heading-tips">Tips</h4>
<p>In general you should use the amount of specificity you need, but not more. In this way, you can craft other selectors to overwrite the rules set by preceding rules without going mad.</p>
<p><code>!important</code> is a highly debated tool that CSS offers us. Many CSS experts advocate against using it. I find myself using it especially when trying out some style and a CSS rule has so much specificity that I need to use <code>!important</code> to make the browser apply my new CSS.</p>
<p>But generally, <code>!important</code> should have no place in your CSS files.</p>
<p>Using the <code>id</code> attribute to style CSS is also debated a lot, since it has a very high specificity. A good alternative is to use classes instead, which have less specificity, and so they are easier to work with, and they are more powerful (you can have multiple classes for an element, and a class can be reused multiple times).</p>
<h4 id="heading-tools-to-calculate-the-specificity">Tools to calculate the specificity</h4>
<p>You can use the site <a target="_blank" href="https://specificity.keegan.st/">https://specificity.keegan.st/</a> to perform the specificity calculation for you automatically.</p>
<p>It’s useful especially if you are trying to figure things out, as it can be a nice feedback tool.</p>
<h3 id="heading-inheritance">INHERITANCE</h3>
<p>When you set some properties on a selector in CSS, they are inherited by all the children of that selector.</p>
<p>I said <em>some</em>, because not all properties show this behaviour.</p>
<p>This happens because some properties make sense to be inherited. This helps us write CSS much more concisely, since we don’t have to explicitly set that property again on every single child.</p>
<p>Some other properties make more sense to <em>not</em> be inherited.</p>
<p>Think about fonts: you don’t need to apply the <code>font-family</code> to every single tag of your page. You set the <code>body</code> tag font, and every child inherits it, along with other properties.</p>
<p>The <code>background-color</code> property, on the other hand, makes little sense to be inherited.</p>
<h4 id="heading-properties-that-inherit">Properties that inherit</h4>
<p>Here is a list of the properties that do inherit. The list is non-comprehensive, but those rules are just the most popular ones you’ll likely use:</p>
<ul>
<li>border-collapse</li>
<li>border-spacing</li>
<li>caption-side</li>
<li>color</li>
<li>cursor</li>
<li>direction</li>
<li>empty-cells</li>
<li>font-family</li>
<li>font-size</li>
<li>font-style</li>
<li>font-variant</li>
<li>font-weight</li>
<li>font-size-adjust</li>
<li>font-stretch</li>
<li>font</li>
<li>letter-spacing</li>
<li>line-height</li>
<li>list-style-image</li>
<li>list-style-position</li>
<li>list-style-type</li>
<li>list-style</li>
<li>orphans</li>
<li>quotes</li>
<li>tab-size</li>
<li>text-align</li>
<li>text-align-last</li>
<li>text-decoration-color</li>
<li>text-indent</li>
<li>text-justify</li>
<li>text-shadow</li>
<li>text-transform</li>
<li>visibility</li>
<li>white-space</li>
<li>widows</li>
<li>word-break</li>
<li>word-spacing</li>
</ul>
<p>I got it from this <a target="_blank" href="https://www.sitepoint.com/css-inheritance-introduction/">nice Sitepoint article</a> on CSS inheritance.</p>
<h4 id="heading-forcing-properties-to-inherit">Forcing properties to inherit</h4>
<p>What if you have a property that’s not inherited by default, and you want it to, in a child?</p>
<p>In the children, you set the property value to the special keyword <code>inherit</code>.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">background-color</span>: yellow;
}

<span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">background-color</span>: inherit;
}
</code></pre>
<h4 id="heading-forcing-properties-to-not-inherit">Forcing properties to NOT inherit</h4>
<p>On the contrary, you might have a property inherited and you want to avoid so.</p>
<p>You can use the <code>revert</code> keyword to revert it. In this case, the value is reverted to the original value the browser gave it in its default stylesheet.</p>
<p>In practice this is rarely used, and most of the times you’ll just set another value for the property to overwrite that inherited value.</p>
<h4 id="heading-other-special-values">Other special values</h4>
<p>In addition to the <code>inherit</code> and <code>revert</code> special keywords we just saw, you can also set any property to:</p>
<ul>
<li><code>initial</code>: use the default browser stylesheet if available. If not, and if the property inherits by default, inherit the value. Otherwise do nothing.</li>
<li><code>unset</code>: if the property inherits by default, inherit. Otherwise do nothing.</li>
</ul>
<h3 id="heading-import">IMPORT</h3>
<p>From any CSS file you can import another CSS file using the <code>@import</code> directive.</p>
<p>Here is how you use it:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(myfile.css)
</code></pre>
<p>url() can manage absolute or relative URLs.</p>
<p>One important thing you need to know is that <code>@import</code> directives must be put before any other CSS in the file, or they will be ignored.</p>
<p>You can use media descriptors to only load a CSS file on the specific media:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(myfile.css) all;
<span class="hljs-keyword">@import</span> url(myfile-screen.css) screen;
<span class="hljs-keyword">@import</span> url(myfile-print.css) print;
</code></pre>
<h3 id="heading-attribute-selectors">ATTRIBUTE SELECTORS</h3>
<p>We already introduced several of the basic CSS selectors: using element selectors, class, id, how to combine them, how to target multiple classes, how to style several selectors in the same rule, how to follow the page hierarchy with child and direct child selectors, and adjacent siblings.</p>
<p>In this section we’ll analyze attribute selectors, and we’ll talk about pseudo class and pseudo element selectors in the next 2 sections.</p>
<h4 id="heading-attribute-presence-selectors">Attribute presence selectors</h4>
<p>The first selector type is the attribute presence selector.</p>
<p>We can check if an element <strong>has</strong> an attribute using the <code>[]</code> syntax. <code>p[id]</code> will select all <code>p</code> tags in the page that have an <code>id</code> attribute, regardless of its value:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span><span class="hljs-selector-attr">[id]</span> {
  <span class="hljs-comment">/* ... */</span>
}
</code></pre>
<h4 id="heading-exact-attribute-value-selectors">Exact attribute value selectors</h4>
<p>Inside the brackets you can check the attribute value using <code>=</code>, and the CSS will be applied only if the attribute matches the exact value specified:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span><span class="hljs-selector-attr">[id=<span class="hljs-string">"my-id"</span>]</span> {
  <span class="hljs-comment">/* ... */</span>
}
</code></pre>
<h4 id="heading-match-an-attribute-value-portion">Match an attribute value portion</h4>
<p>While <code>=</code> lets us check for exact value, we have other operators:</p>
<ul>
<li><code>*=</code> checks if the attribute contains the partial</li>
<li><code>^=</code> checks if the attribute starts with the partial</li>
<li><code>$=</code> checks if the attribute ends with the partial</li>
<li><code>|=</code> checks if the attribute starts with the partial and it's followed by a dash (common in classes, for example), or just contains the partial</li>
<li><code>~=</code> checks if the partial is contained in the attribute, but separated by spaces from the rest</li>
</ul>
<p>All the checks we mentioned are <strong>case sensitive</strong>.</p>
<p>If you add an <code>i</code> just before the closing bracket, the check will be case insensitive. It's supported in many browsers but not in all, check <a target="_blank" href="https://caniuse.com/#feat=css-case-insensitive">https://caniuse.com/#feat=css-case-insensitive</a>.</p>
<h3 id="heading-pseudo-classes">PSEUDO-CLASSES</h3>
<p>Pseudo classes are predefined keywords that are used to select an element based on its <strong>state</strong>, or to target a specific child.</p>
<p>They start with a <strong>single colon</strong> <code>:</code>.</p>
<p>They can be used as part of a selector, and they are very useful to style active or visited links, for example, change the style on hover, focus, or target the first child, or odd rows. Very handy in many cases.</p>
<p>These are the most popular pseudo classes you will likely use:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ACo1IxL9QFOQvDYkMigh3FXw717fjM2ChP3w" alt="Image" width="792" height="940" loading="lazy"></p>
<p>Let’s do an example. A common one, actually. You want to style a link, so you create a CSS rule to target the <code>a</code> element:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">a</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p>Things seem to work fine, until you click one link. The link goes back to the predefined color (blue) when you click it. Then when you open the link and go back to the page, now the link is blue.</p>
<p>Why does that happen?</p>
<p>Because the link when clicked changes state, and goes in the <code>:active</code> state. And when it's been visited, it is in the <code>:visited</code> state. Forever, until the user clears the browsing history.</p>
<p>So, to correctly make the link yellow across all states, you need to write</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">a</span>,
<span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:visited</span>,
<span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:active</span> {
  <span class="hljs-attribute">color</span>: yellow;
}
</code></pre>
<p><code>:nth-child()</code> deserves a special mention. It can be used to target odd or even children with <code>:nth-child(odd)</code> and <code>:nth-child(even)</code>.</p>
<p>It is commonly used in lists to color odd lines differently from even lines:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">ul</span><span class="hljs-selector-pseudo">:nth-child(odd)</span> {
  <span class="hljs-attribute">color</span>: white;
    <span class="hljs-attribute">background-color</span>: black;
}
</code></pre>
<p>You can also use it to target the first 3 children of an element with <code>:nth-child(-n+3)</code>. Or you can style 1 in every 5 elements with <code>:nth-child(5n)</code>.</p>
<p>Some pseudo classes are just used for printing, like <code>:first</code>, <code>:left</code>, <code>:right</code>, so you can target the first page, all the left pages, and all the right pages, which are usually styled slightly differently.</p>
<h3 id="heading-pseudo-elements">PSEUDO-ELEMENTS</h3>
<h4 id="heading-pseudo-elements-are-used-to-style-a-specific-part-of-an-element">Pseudo-elements are used to style a specific part of an element.</h4>
<p>They start with a double colon <code>::</code>.</p>
<blockquote>
<p><em>Sometimes you will spot them in the wild with a single colon, but this is only a syntax supported for backwards compatibility reasons. You should use 2 colons to distinguish them from pseudo-classes.</em></p>
</blockquote>
<p><code>::before</code> and <code>::after</code> are probably the most used pseudo-elements. They are used to add content before or after an element, like icons for example.</p>
<p>Here’s the list of the pseudo-elements:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/9FIuV0uCcudGyplaJcgQAEqK7sTSwhRCIZYd" alt="Image" width="799" height="258" loading="lazy"></p>
<p>Let’s do an example. Say you want to make the first line of a paragraph slightly bigger in font size, a common thing in typography:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span><span class="hljs-selector-pseudo">::first-line</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
}
</code></pre>
<p>Or maybe you want the first letter to be bolder:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span><span class="hljs-selector-pseudo">::first-letter</span> {
  <span class="hljs-attribute">font-weight</span>: bolder;
}
</code></pre>
<p><code>::after</code> and <code>::before</code> are a bit less intuitive. I remember using them when I had to add icons using CSS.</p>
<p>You specify the <code>content</code> property to insert any kind of content after or before an element:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span><span class="hljs-selector-pseudo">::before</span> {
  <span class="hljs-attribute">content</span>: <span class="hljs-built_in">url</span>(/myimage.png);
}

<span class="hljs-selector-class">.myElement</span><span class="hljs-selector-pseudo">::before</span> {
    <span class="hljs-attribute">content</span>: <span class="hljs-string">"Hey Hey!"</span>;
}
</code></pre>
<h3 id="heading-colors">COLORS</h3>
<p>By default an HTML page is rendered by web browsers quite sadly in terms of the colors used.</p>
<p>We have a white background, black color, and blue links. That’s it.</p>
<p>Luckily CSS gives us the ability to add colors to our designs.</p>
<p>We have these properties:</p>
<ul>
<li><code>color</code></li>
<li><code>background-color</code></li>
<li><code>border-color</code></li>
</ul>
<p>All of them accept a <strong>color value</strong>, which can be in different forms.</p>
<h4 id="heading-named-colors">Named colors</h4>
<p>First, we have CSS keywords that define colors. CSS started with 16, but today there is a huge number of colors names:</p>
<ul>
<li><code>aliceblue</code></li>
<li><code>antiquewhite</code></li>
<li><code>aqua</code></li>
<li><code>aquamarine</code></li>
<li><code>azure</code></li>
<li><code>beige</code></li>
<li><code>bisque</code></li>
<li><code>black</code></li>
<li><code>blanchedalmond</code></li>
<li><code>blue</code></li>
<li><code>blueviolet</code></li>
<li><code>brown</code></li>
<li><code>burlywood</code></li>
<li><code>cadetblue</code></li>
<li><code>chartreuse</code></li>
<li><code>chocolate</code></li>
<li><code>coral</code></li>
<li><code>cornflowerblue</code></li>
<li><code>cornsilk</code></li>
<li><code>crimson</code></li>
<li><code>cyan</code></li>
<li><code>darkblue</code></li>
<li><code>darkcyan</code></li>
<li><code>darkgoldenrod</code></li>
<li><code>darkgray</code></li>
<li><code>darkgreen</code></li>
<li><code>darkgrey</code></li>
<li><code>darkkhaki</code></li>
<li><code>darkmagenta</code></li>
<li><code>darkolivegreen</code></li>
<li><code>darkorange</code></li>
<li><code>darkorchid</code></li>
<li><code>darkred</code></li>
<li><code>darksalmon</code></li>
<li><code>darkseagreen</code></li>
<li><code>darkslateblue</code></li>
<li><code>darkslategray</code></li>
<li><code>darkslategrey</code></li>
<li><code>darkturquoise</code></li>
<li><code>darkviolet</code></li>
<li><code>deeppink</code></li>
<li><code>deepskyblue</code></li>
<li><code>dimgray</code></li>
<li><code>dimgrey</code></li>
<li><code>dodgerblue</code></li>
<li><code>firebrick</code></li>
<li><code>floralwhite</code></li>
<li><code>forestgreen</code></li>
<li><code>fuchsia</code></li>
<li><code>gainsboro</code></li>
<li><code>ghostwhite</code></li>
<li><code>gold</code></li>
<li><code>goldenrod</code></li>
<li><code>gray</code></li>
<li><code>green</code></li>
<li><code>greenyellow</code></li>
<li><code>grey</code></li>
<li><code>honeydew</code></li>
<li><code>hotpink</code></li>
<li><code>indianred</code></li>
<li><code>indigo</code></li>
<li><code>ivory</code></li>
<li><code>khaki</code></li>
<li><code>lavender</code></li>
<li><code>lavenderblush</code></li>
<li><code>lawngreen</code></li>
<li><code>lemonchiffon</code></li>
<li><code>lightblue</code></li>
<li><code>lightcoral</code></li>
<li><code>lightcyan</code></li>
<li><code>lightgoldenrodyellow</code></li>
<li><code>lightgray</code></li>
<li><code>lightgreen</code></li>
<li><code>lightgrey</code></li>
<li><code>lightpink</code></li>
<li><code>lightsalmon</code></li>
<li><code>lightseagreen</code></li>
<li><code>lightskyblue</code></li>
<li><code>lightslategray</code></li>
<li><code>lightslategrey</code></li>
<li><code>lightsteelblue</code></li>
<li><code>lightyellow</code></li>
<li><code>lime</code></li>
<li><code>limegreen</code></li>
<li><code>linen</code></li>
<li><code>magenta</code></li>
<li><code>maroon</code></li>
<li><code>mediumaquamarine</code></li>
<li><code>mediumblue</code></li>
<li><code>mediumorchid</code></li>
<li><code>mediumpurple</code></li>
<li><code>mediumseagreen</code></li>
<li><code>mediumslateblue</code></li>
<li><code>mediumspringgreen</code></li>
<li><code>mediumturquoise</code></li>
<li><code>mediumvioletred</code></li>
<li><code>midnightblue</code></li>
<li><code>mintcream</code></li>
<li><code>mistyrose</code></li>
<li><code>moccasin</code></li>
<li><code>navajowhite</code></li>
<li><code>navy</code></li>
<li><code>oldlace</code></li>
<li><code>olive</code></li>
<li><code>olivedrab</code></li>
<li><code>orange</code></li>
<li><code>orangered</code></li>
<li><code>orchid</code></li>
<li><code>palegoldenrod</code></li>
<li><code>palegreen</code></li>
<li><code>paleturquoise</code></li>
<li><code>palevioletred</code></li>
<li><code>papayawhip</code></li>
<li><code>peachpuff</code></li>
<li><code>peru</code></li>
<li><code>pink</code></li>
<li><code>plum</code></li>
<li><code>powderblue</code></li>
<li><code>purple</code></li>
<li><code>rebeccapurple</code></li>
<li><code>red</code></li>
<li><code>rosybrown</code></li>
<li><code>royalblue</code></li>
<li><code>saddlebrown</code></li>
<li><code>salmon</code></li>
<li><code>sandybrown</code></li>
<li><code>seagreen</code></li>
<li><code>seashell</code></li>
<li><code>sienna</code></li>
<li><code>silver</code></li>
<li><code>skyblue</code></li>
<li><code>slateblue</code></li>
<li><code>slategray</code></li>
<li><code>slategrey</code></li>
<li><code>snow</code></li>
<li><code>springgreen</code></li>
<li><code>steelblue</code></li>
<li><code>tan</code></li>
<li><code>teal</code></li>
<li><code>thistle</code></li>
<li><code>tomato</code></li>
<li><code>turquoise</code></li>
<li><code>violet</code></li>
<li><code>wheat</code></li>
<li><code>white</code></li>
<li><code>whitesmoke</code></li>
<li><code>yellow</code></li>
<li><code>yellowgreen</code></li>
</ul>
<p>plus <code>tranparent</code>, and <code>currentColor</code> which points to the <code>color</code> property, for example it’s useful to make the <code>border-color</code> inherit it.</p>
<p>They are defined in the <a target="_blank" href="https://www.w3.org/TR/css-color-4/">CSS Color Module, Level 4</a>. They are case insensitive.</p>
<p>Wikipedia has a <a target="_blank" href="https://en.wikipedia.org/wiki/Web_colors">nice table</a> which lets you pick the perfect color by its name.</p>
<p>Named colors are not the only option.</p>
<h3 id="heading-rgb-and-rgba">RGB and RGBa</h3>
<p>You can use the <code>rgb()</code> function to calculate a color from its RGB notation, which sets the color based on its red-green-blue parts. From 0 to 255:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>); <span class="hljs-comment">/* white */</span>
    <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>); <span class="hljs-comment">/* black */</span>
}
</code></pre>
<p><code>rgba()</code> lets you add the alpha channel to enter a transparent part. That can be a number from 0 to 1:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.5</span>);
}
</code></pre>
<h4 id="heading-hexadecimal-notation">Hexadecimal notation</h4>
<p>Another option is to express the RGB parts of the colors in the hexadecimal notation, which is composed by 3 blocks.</p>
<p>Black, which is <code>rgb(0,0,0)</code> is expressed as <code>#000000</code> or <code>#000</code> (we can shortcut the 2 numbers to 1 if they are equal).</p>
<p>White, <code>rgb(255,255,255)</code> can be expressed as <code>#ffffff</code> or <code>#fff</code>.</p>
<p>The hexadecimal notation lets us express a number from 0 to 255 in just 2 digits, since they can go from 0 to “15” (f).</p>
<p>We can add the alpha channel by adding 1 or 2 more digits at the end, for example <code>#00000033</code>. Not all browsers support the shortened notation, so use all 6 digits to express the RGB part.</p>
<h4 id="heading-hsl-and-hsla">HSL and HSLa</h4>
<p>This is a more recent addition to CSS.</p>
<p>HSL = Hue Saturation Lightness.</p>
<p>In this notation, black is <code>hsl(0, 0%, 0%)</code> and white is <code>hsl(0, 0%, 100%)</code>.</p>
<p>If you are more familiar with HSL than RGB because of your past knowledge, you can definitely use that.</p>
<p>You also have <code>hsla()</code> which adds the alpha channel to the mix, again a number from 0 to 1: <code>hsl(0, 0%, 0%, 0.5)</code></p>
<h3 id="heading-units">UNITS</h3>
<p>One of the things you’ll use every day in CSS are units. They are used to set lengths, paddings, margins, align elements and so on.</p>
<p>Things like <code>px</code>, <code>em</code>, <code>rem</code>, or percentages.</p>
<p>They are everywhere. There are some obscure ones, too. We’ll go through each of them in this section.</p>
<h4 id="heading-pixels">Pixels</h4>
<p>The most widely used measurement unit. A pixel does not actually correlate to a physical pixel on your screen, as that varies, a lot, by device (think high-DPI devices vs non-retina devices).</p>
<p>There is a convention that make this unit work consistently across devices.</p>
<h4 id="heading-percentages">Percentages</h4>
<p>Another very useful measure, percentages let you specify values in percentages of that parent element’s corresponding property.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.parent</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">400px</span>;
}

<span class="hljs-selector-class">.child</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">50%</span>; <span class="hljs-comment">/* = 200px */</span>
}
</code></pre>
<h4 id="heading-real-world-measurement-units">Real-world measurement units</h4>
<p>We have those measurement units which are translated from the outside world. Mostly useless on screen, they can be useful for print stylesheets. They are:</p>
<ul>
<li><code>cm</code> a centimeter (maps to 37.8 pixels)</li>
<li><code>mm</code> a millimeter (0.1cm)</li>
<li><code>q</code> a quarter of a millimeter</li>
<li><code>in</code> an inch (maps to 96 pixels)</li>
<li><code>pt</code> a point (1 inch = 72 points)</li>
<li><code>pc</code> a pica (1 pica = 12 points)</li>
</ul>
<h4 id="heading-relative-units">Relative units</h4>
<ul>
<li><code>em</code> is the value assigned to that element's <code>font-size</code>, therefore its exact value changes between elements. It does not change depending on the font used, just on the font size. In typography this measures the width of the <code>m</code> letter.</li>
<li><code>rem</code> is similar to <code>em</code>, but instead of varying on the current element font size, it uses the root element (<code>html</code>) font size. You set that font size once, and <code>rem</code> will be a consistent measure across all the page.</li>
<li><code>ex</code> is like <code>em</code>, but instead of measuring the width of <code>m</code>, it measures the height of the <code>x</code> letter. It can change depending on the font used, and on the font size.</li>
<li><code>ch</code> is like <code>ex</code> but instead of measuring the height of <code>x</code> it measures the width of <code>0</code> (zero).</li>
</ul>
<h4 id="heading-viewport-units">Viewport units</h4>
<ul>
<li><code>vw</code> the <strong>viewport width unit</strong> represents a percentage of the viewport width. <code>50vw</code> means 50% of the viewport width.</li>
<li><code>vh</code> the <strong>viewport height unit</strong> represents a percentage of the viewport height. <code>50vh</code> means 50% of the viewport height.</li>
<li><code>vmin</code> the <strong>viewport minimum unit</strong> represents the minimum between the height or width in terms of percentage. <code>30vmin</code> is the 30% of the current width or height, depending which one is smaller</li>
<li><code>vmax</code> the <strong>viewport maximum unit</strong> represents the maximum between the height or width in terms of percentage. <code>30vmax</code> is the 30% of the current width or height, depending which one is bigger</li>
</ul>
<h4 id="heading-fraction-units">Fraction units</h4>
<p><code>fr</code> are fraction units, and they are used in CSS Grid to divide space into fractions.</p>
<p>We’ll talk about them in the context of CSS Grid later on.</p>
<h3 id="heading-url">URL</h3>
<p>When we talk about background images, <code>@import</code>, and more, we use the <code>url()</code> function to load a resource:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">url</span>(test.png);
}
</code></pre>
<p>In this case I used a relative URL, which searches the file in the folder where the CSS file is defined.</p>
<p>I could go one level back</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">url</span>(../test.png);
}
</code></pre>
<p>or go into a folder</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">url</span>(subfolder/test.png);
}
</code></pre>
<p>Or I could load a file starting from the root of the domain where the CSS is hosted:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">url</span>(/test.png);
}
</code></pre>
<p>Or I could use an absolute URL to load an external resource:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">url</span>(https://mysite.com/test.png);
}
</code></pre>
<h3 id="heading-calc">CALC</h3>
<p>The <code>calc()</code> function lets you perform basic math operations on values, and it's especially useful when you need to add or subtract a length value from a percentage.</p>
<p>This is how it works:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
    <span class="hljs-attribute">max-width</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">80%</span> - <span class="hljs-number">100px</span>)
}
</code></pre>
<p>It returns a length value, so it can be used anywhere you expect a pixel value.</p>
<p>You can perform</p>
<ul>
<li>additions using <code>+</code></li>
<li>subtractions using <code>-</code></li>
<li>multiplication using <code>*</code></li>
<li>division using <code>/</code></li>
</ul>
<blockquote>
<p><em>One caveat: with addition and subtraction, the space around the operator is mandatory, otherwise it does not work as expected.</em></p>
</blockquote>
<p>Examples:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
    <span class="hljs-attribute">max-width</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> / <span class="hljs-number">3</span>)
}

<span class="hljs-selector-tag">div</span> {
    <span class="hljs-attribute">max-width</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> + <span class="hljs-number">3px</span>)
}
</code></pre>
<h3 id="heading-backgrounds">BACKGROUNDS</h3>
<p>The background of an element can be changed using several CSS properties:</p>
<ul>
<li><code>background-color</code></li>
<li><code>background-image</code></li>
<li><code>background-clip</code></li>
<li><code>background-position</code></li>
<li><code>background-origin</code></li>
<li><code>background-repeat</code></li>
<li><code>background-attachment</code></li>
<li><code>background-size</code></li>
</ul>
<p>and the shorthand property <code>background</code>, which allows us to shorten definitions and group them on a single line.</p>
<p><code>background-color</code> accepts a color value, which can be one of the color keywords, or an <code>rgb</code> or <code>hsl</code> value:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">background-color</span>: yellow;
}

<span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#333</span>;
}
</code></pre>
<p>Instead of using a color, you can use an image as background to an element, by specifying the image location URL:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">url</span>(image.png);
}
</code></pre>
<p><code>background-clip</code> lets you determine the area used by the background image, or color. The default value is <code>border-box</code>, which extends up to the border outer edge.</p>
<p>Other values are</p>
<ul>
<li><code>padding-box</code> to extend the background up to the padding edge, without the border</li>
<li><code>content-box</code> to extend the background up to the content edge, without the padding</li>
<li><code>inherit</code> to apply the value of the parent</li>
</ul>
<p>When using an image as background you will want to set the position of the image placement using the <code>background-position</code> property: <code>left</code>, <code>right</code>, <code>center</code> are all valid values for the X axis, and <code>top</code>, <code>bottom</code> for the Y axis:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-position</span>: top right;
}
</code></pre>
<p>If the image is smaller than the background, you need to set the behavior using <code>background-repeat</code>. Should it <code>repeat-x</code>, <code>repeat-y</code> or <code>repeat</code> on all the axes? This last one is the default value. Another value is <code>no-repeat</code>.</p>
<p><code>background-origin</code> lets you choose where the background should be applied: to the entire element including padding (default) using <code>padding-box</code>, to the entire element including the border using <code>border-box</code>, to the element without the padding using <code>content-box</code>.</p>
<p>With <code>background-attachment</code> we can attach the background to the viewport, so that scrolling will not affect the background:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-attachment</span>: fixed;
}
</code></pre>
<p>By default the value is <code>scroll</code>. There is another value, <code>local</code>. The best way to visualize their behavior is <a target="_blank" href="https://codepen.io/BernLeech/pen/mMNKJV">this Codepen</a>.</p>
<p>The last background property is <code>background-size</code>. We can use 3 keywords: <code>auto</code>, <code>cover</code> and <code>contain</code>. <code>auto</code> is the default.</p>
<p><code>cover</code> expands the image until the entire element is covered by the background.</p>
<p><code>contain</code> stops expanding the background image when one dimension (x or y) covers the whole smallest edge of the image, so it's fully contained into the element.</p>
<p>You can also specify a length value, and if so it sets the width of the background image (and the height is automatically defined):</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">100%</span>;
}
</code></pre>
<p>If you specify 2 values, one is the width and the second is the height:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background-size</span>: <span class="hljs-number">800px</span> <span class="hljs-number">600px</span>;
}
</code></pre>
<p>The shorthand property <code>background</code> allows to shorten definitions and group them on a single line.</p>
<p>This is an example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">url</span>(bg.png) top left no-repeat;
}
</code></pre>
<p>If you use an image, and the image could not be loaded, you can set a fallback color:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">url</span>(image.png) yellow;
}
</code></pre>
<p>You can also set a gradient as background:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">linear-gradient</span>(#fff, #<span class="hljs-number">333</span>);
}
</code></pre>
<h3 id="heading-comments">COMMENTS</h3>
<p>CSS gives you the ability to write comments in a CSS file, or in the <code>style</code> tag in the page header</p>
<p>The format is the <code>/* this is a comment */</code> C-style (or JavaScript-style, if you prefer) comments.</p>
<p>This is a multiline comment. Until you add the closing <code>*/</code> token, the all the lines found after the opening one are commented.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#name</span> { <span class="hljs-attribute">display</span>: block; } <span class="hljs-comment">/* Nice rule! */</span>

<span class="hljs-comment">/* #name { display: block; } */</span>

<span class="hljs-selector-id">#name</span> {
    <span class="hljs-attribute">display</span>: block; <span class="hljs-comment">/*
    color: red;
    */</span>
}
</code></pre>
<p>CSS does not have inline comments, like <code>//</code> in C or JavaScript.</p>
<p>Pay attention though — if you add <code>//</code> before a rule, the rule will not be applied, looking like the comment worked. In reality, CSS detected a syntax error and due to how it works it ignored the line with the error, and went straight to the next line.</p>
<p>Knowing this approach lets you purposefully write inline comments, although you have to be careful because you can’t add random text like you can in a block comment.</p>
<p>For example:</p>
<pre><code class="lang-css">// <span class="hljs-selector-tag">Nice</span> <span class="hljs-selector-tag">rule</span>!
<span class="hljs-selector-id">#name</span> { <span class="hljs-attribute">display</span>: block; }
</code></pre>
<p>In this case, due to how CSS works, the <code>#name</code> rule is actually commented out. You can find more details <a target="_blank" href="https://www.xanthir.com/b4U10">here</a> if you find this interesting. To avoid shooting yourself in the foot, just avoid using inline comments and rely on block comments.</p>
<h3 id="heading-custom-properties">CUSTOM PROPERTIES</h3>
<p>In the last few years CSS preprocessors have had a lot of success. It was very common for greenfield projects to start with Less or Sass. And it’s still a very popular technology.</p>
<p>The main benefits of those technologies are, in my opinion:</p>
<ul>
<li>They allow you to nest selectors</li>
<li>The provide an easy imports functionality</li>
<li>They give you variables</li>
</ul>
<p>Modern CSS has a new powerful feature called <strong>CSS Custom Properties</strong>, also commonly known as <strong>CSS Variables</strong>.</p>
<p>CSS is not a programming language like <a target="_blank" href="https://flaviocopes.com/javascript/">JavaScript</a>, Python, PHP, Ruby or Go where variables are key to do something useful. CSS is very limited in what it can do, and it’s mainly a declarative syntax to tell browsers how they should display an HTML page.</p>
<p>But a variable is a variable: a name that refers to a value, and variables in CSS help reduce repetition and inconsistencies in your CSS, by centralizing the values definition.</p>
<p>And it introduces a unique feature that CSS preprocessors won’t ever have: <strong>you can access and change the value of a CSS Variable programmatically using JavaScript</strong>.</p>
<h4 id="heading-the-basics-of-using-variables">The basics of using variables</h4>
<p>A CSS Variable is defined with a special syntax, prepending <strong>two dashes</strong> to a name (<code>--variable-name</code>), then a colon and a value. Like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--primary-color</span>: yellow;
}
</code></pre>
<p>(more on <code>:root</code> later)</p>
<p>You can access the variable value using <code>var()</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--primary-color)
}
</code></pre>
<p>The variable value can be any valid CSS value, for example:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--default-padding</span>: <span class="hljs-number">30px</span> <span class="hljs-number">30px</span> <span class="hljs-number">20px</span> <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">--default-color</span>: red;
  <span class="hljs-attribute">--default-background</span>: <span class="hljs-number">#fff</span>;
}
</code></pre>
<h4 id="heading-create-variables-inside-any-element">Create variables inside any element</h4>
<p>CSS Variables can be defined inside any element. Some examples:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--default-color</span>: red;
}

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">--default-color</span>: red;
}

<span class="hljs-selector-tag">main</span> {
  <span class="hljs-attribute">--default-color</span>: red;
}

<span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">--default-color</span>: red;
}

<span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">--default-color</span>: red;
}

<span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:hover</span> {
  <span class="hljs-attribute">--default-color</span>: red;
}
</code></pre>
<p>What changes in those different examples is the <strong>scope</strong>.</p>
<h4 id="heading-variables-scope">Variables scope</h4>
<p>Adding variables to a selector makes them available to all the children of it.</p>
<p>In the example above you saw the use of <code>:root</code> when defining a CSS variable:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--primary-color</span>: yellow;
}
</code></pre>
<p><code>:root</code> is a CSS pseudo-class that identifies the root element of a tree.</p>
<p>In the context of an HTML document, using the <code>:root</code> selector points to the <code>html</code> element, except that <code>:root</code> has higher specificity (takes priority).</p>
<p>In the context of an SVG image, <code>:root</code> points to the <code>svg</code> tag.</p>
<p>Adding a CSS custom property to <code>:root</code> makes it available to all the elements in the page.</p>
<p>If you add a variable inside a <code>.container</code> selector, it's only going to be available to children of <code>.container</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">--secondary-color</span>: yellow;
}
</code></pre>
<p>and using it outside of this element is not going to work.</p>
<p>Variables can be <strong>reassigned</strong>:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--primary-color</span>: yellow;
}

<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">--primary-color</span>: blue;
}
</code></pre>
<p>Outside <code>.container</code>, <code>--primary-color</code> will be <em>yellow</em>, but inside it will be <em>blue</em>.</p>
<p>You can also assign or overwrite a variable inside the HTML using <strong>inline styles</strong>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"--primary-color: orange;"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- ... --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
</code></pre>
<blockquote>
<p><em>CSS Variables follow the normal CSS cascading rules, with precedence set according to specificity.</em></p>
</blockquote>
<h4 id="heading-interacting-with-a-css-variable-value-using-javascript">Interacting with a CSS Variable value using JavaScript</h4>
<p>The coolest thing with CSS Variables is the ability to access and edit them using JavaScript.</p>
<p>Here’s how you set a variable value using plain JavaScript:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> element = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'my-element'</span>)
element.style.setProperty(<span class="hljs-string">'--variable-name'</span>, <span class="hljs-string">'a-value'</span>)
</code></pre>
<p>This code below can be used to access a variable value instead, in case the variable is defined on <code>:root</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> styles = getComputedStyle(<span class="hljs-built_in">document</span>.documentElement)
<span class="hljs-keyword">const</span> value = <span class="hljs-built_in">String</span>(styles.getPropertyValue(<span class="hljs-string">'--variable-name'</span>)).trim()
</code></pre>
<p>Or, to get the style applied to a specific element, in case of variables set with a different scope:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> element = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'my-element'</span>)
<span class="hljs-keyword">const</span> styles = getComputedStyle(element)
<span class="hljs-keyword">const</span> value = <span class="hljs-built_in">String</span>(styles.getPropertyValue(<span class="hljs-string">'--variable-name'</span>)).trim()
</code></pre>
<h4 id="heading-handling-invalid-values">Handling invalid values</h4>
<p>If a variable is assigned to a property which does not accept the variable value, it’s considered invalid.</p>
<p>For example you might pass a pixel value to a <code>position</code> property, or a rem value to a color property.</p>
<p>In this case the line is considered invalid and is ignored.</p>
<h4 id="heading-browser-support">Browser support</h4>
<p>Browser support for CSS Variables is <strong>very good</strong>, <a target="_blank" href="https://www.caniuse.com/#feat=css-variables">according to Can I Use</a>.</p>
<p>CSS Variables are here to stay, and you can use them today if you don’t need to support Internet Explorer and old versions of the other browsers.</p>
<p>If you need to support older browsers you can use libraries like <a target="_blank" href="https://flaviocopes.com/postcss/">PostCSS</a> or <a target="_blank" href="http://www.myth.io/">Myth</a>, but you’ll lose the ability to interact with variables via JavaScript or the Browser Developer Tools, as they are transpiled to good old variable-less CSS (and as such, you lose most of the power of CSS Variables).</p>
<h4 id="heading-css-variables-are-case-sensitive">CSS Variables are case sensitive</h4>
<p>This variable:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">--width</span>: 100<span class="hljs-selector-tag">px</span>;
</code></pre>
<p>is different than this one:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">--Width</span>: 100<span class="hljs-selector-tag">px</span>;
</code></pre>
<h4 id="heading-math-in-css-variables">Math in CSS Variables</h4>
<p>To do math in CSS Variables, you need to use <code>calc()</code>, for example:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--default-left-padding</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">10px</span> * <span class="hljs-number">2</span>);
}
</code></pre>
<h4 id="heading-media-queries-with-css-variables">Media queries with CSS Variables</h4>
<p>Nothing special here. CSS Variables normally apply to media queries:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">--width</span>: <span class="hljs-number">500px</span>;
}

<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">1000px</span>) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">700px</span>) {
  <span class="hljs-selector-tag">--width</span>: 800<span class="hljs-selector-tag">px</span>;
}

<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-built_in">var</span>(--width);
}
</code></pre>
<h4 id="heading-setting-a-fallback-value-for-var">Setting a fallback value for var()</h4>
<p><code>var()</code> accepts a second parameter, which is the default fallback value when the variable value is not set:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-built_in">var</span>(--default-margin, <span class="hljs-number">30px</span>);
}
</code></pre>
<h3 id="heading-fonts">FONTS</h3>
<p>At the dawn of the web you only had a handful of fonts you could choose from.</p>
<p>Thankfully today you can load any kind of font on your pages.</p>
<p>CSS has gained many nice capabilities over the years in regards to fonts.</p>
<p>The <code>font</code> property is the shorthand for a number of properties:</p>
<ul>
<li><code>font-family</code></li>
<li><code>font-weight</code></li>
<li><code>font-stretch</code></li>
<li><code>font-style</code></li>
<li><code>font-size</code></li>
</ul>
<p>Let’s see each one of them and then we’ll cover <code>font</code>.</p>
<p>Then we’ll talk about how to load custom fonts, using <code>@import</code> or <code>@font-face</code>, or by loading a font stylesheet.</p>
<h4 id="heading-font-family"><code>font-family</code></h4>
<p>Sets the font <em>family</em> that the element will use.</p>
<p>Why “family”? Because what we know as a font is actually composed of several sub-fonts which provide all the style (bold, italic, light..) we need.</p>
<p>Here’s an example from my Mac’s Font Book app — the Fira Code font family hosts several dedicated fonts underneath:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/3eSWEQuM-orkdVa7xATJ5p9sH2Te-clkilVI" alt="Image" width="800" height="460" loading="lazy"></p>
<p>This property lets you select a specific font, for example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: Helvetica;
}
</code></pre>
<p>You can set multiple values, so the second option will be used if the first cannot be used for some reason (if it’s not found on the machine, or the network connection to download the font failed, for example):</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: Helvetica, Arial;
}
</code></pre>
<p>I used some specific fonts up to now, ones we call <strong>Web Safe Fonts</strong>, as they are pre-installed on different operating systems.</p>
<p>We divide them in Serif, Sans-Serif, and Monospace fonts. Here’s a list of some of the most popular ones:</p>
<p><strong>Serif</strong></p>
<ul>
<li>Georgia</li>
<li>Palatino</li>
<li>Times New Roman</li>
<li>Times</li>
</ul>
<p><strong>Sans-Serif</strong></p>
<ul>
<li>Arial</li>
<li>Helvetica</li>
<li>Verdana</li>
<li>Geneva</li>
<li>Tahoma</li>
<li>Lucida Grande</li>
<li>Impact</li>
<li>Trebuchet MS</li>
<li>Arial Black</li>
</ul>
<p><strong>Monospace</strong></p>
<ul>
<li>Courier New</li>
<li>Courier</li>
<li>Lucida Console</li>
<li>Monaco</li>
</ul>
<p>You can use all of those as <code>font-family</code> properties, but they are not guaranteed to be there for every system. Others exist, too, with a varying level of support.</p>
<p>You can also use generic names:</p>
<ul>
<li><code>sans-serif</code> a font without ligatures</li>
<li><code>serif</code> a font with ligatures</li>
<li><code>monospace</code> a font especially good for code</li>
<li><code>cursive</code> used to simulate handwritten pieces</li>
<li><code>fantasy</code> the name says it all</li>
</ul>
<p>Those are typically used at the end of a <code>font-family</code> definition, to provide a fallback value in case nothing else can be applied:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: Helvetica, Arial, sans-serif;
}
</code></pre>
<h4 id="heading-font-weight"><code>font-weight</code></h4>
<p>This property sets the width of a font. You can use those predefined values:</p>
<ul>
<li>normal</li>
<li>bold</li>
<li>bolder (relative to the parent element)</li>
<li>lighter (relative to the parent element)</li>
</ul>
<p>Or using the numeric keywords</p>
<ul>
<li>100</li>
<li>200</li>
<li>300</li>
<li>400, mapped to <code>normal</code></li>
<li>500</li>
<li>600</li>
<li>700 mapped to <code>bold</code></li>
<li>800</li>
<li>900</li>
</ul>
<p>where 100 is the lightest font, and 900 is the boldest.</p>
<p>Some of those numeric values might not map to a font, because that must be provided in the font family. When one is missing, CSS makes that number be at least as bold as the preceding one, so you might have numbers that point to the same font.</p>
<h4 id="heading-font-stretch"><code>font-stretch</code></h4>
<p>Allows you to choose a narrow or wide face of the font, if available.</p>
<p>This is important: the font must be equipped with different faces.</p>
<p>Values allowed are, from narrower to wider:</p>
<ul>
<li><code>ultra-condensed</code></li>
<li><code>extra-condensed</code></li>
<li><code>condensed</code></li>
<li><code>semi-condensed</code></li>
<li><code>normal</code></li>
<li><code>semi-expanded</code></li>
<li><code>expanded</code></li>
<li><code>extra-expanded</code></li>
<li><code>ultra-expanded</code></li>
</ul>
<h4 id="heading-font-style"><code>font-style</code></h4>
<p>Allows you to apply an italic style to a font:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">font-style</span>: italic;
}
</code></pre>
<p>This property also allows the values <code>oblique</code> and <code>normal</code>. There is very little, if any, difference between using <code>italic</code> and <code>oblique</code>. The first is easier to me, as HTML already offers an <code>i</code> element which means italic.</p>
<h4 id="heading-font-size"><code>font-size</code></h4>
<p>This property is used to determine the size of fonts.</p>
<p>You can pass 2 kinds of values:</p>
<ol>
<li>a length value, like <code>px</code>, <code>em</code>, <code>rem</code> etc, or a percentage</li>
<li>a predefined value keyword</li>
</ol>
<p>In the second case, the values you can use are:</p>
<ul>
<li>xx-small</li>
<li>x-small</li>
<li>small</li>
<li>medium</li>
<li>large</li>
<li>x-large</li>
<li>xx-large</li>
<li>smaller (relative to the parent element)</li>
<li>larger (relative to the parent element)</li>
</ul>
<p>Usage:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">font-size</span>: medium;
}
</code></pre>
<h4 id="heading-font-variant"><code>font-variant</code></h4>
<p>This property was originally used to change the text to small caps, and it had just 3 valid values:</p>
<ul>
<li><code>normal</code></li>
<li><code>inherit</code></li>
<li><code>small-caps</code></li>
</ul>
<p>Small caps means the text is rendered in “smaller caps” beside its uppercase letters.</p>
<h4 id="heading-font"><code>font</code></h4>
<p>The <code>font</code> property lets you apply different font properties in a single one, reducing the clutter.</p>
<p>We must at least set 2 properties, <code>font-size</code> and <code>font-family</code>, the others are optional:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font</span>: <span class="hljs-number">20px</span> Helvetica;
}
</code></pre>
<p>If we add other properties, they need to be put in the correct order.</p>
<p>This is the order:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">font</span>: &lt;<span class="hljs-selector-tag">font-stretch</span>&gt; &lt;<span class="hljs-selector-tag">font-style</span>&gt; &lt;<span class="hljs-selector-tag">font-variant</span>&gt; &lt;<span class="hljs-selector-tag">font-weight</span>&gt; &lt;<span class="hljs-selector-tag">font-size</span>&gt; &lt;<span class="hljs-selector-tag">line-height</span>&gt; &lt;<span class="hljs-selector-tag">font-family</span>&gt;;
</code></pre>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font</span>: italic bold <span class="hljs-number">20px</span> Helvetica;
}

<span class="hljs-selector-tag">section</span> {
  <span class="hljs-attribute">font</span>: small-caps bold <span class="hljs-number">20px</span> Helvetica;
}
</code></pre>
<h4 id="heading-loading-custom-fonts-using-font-face">Loading custom fonts using <code>@font-face</code></h4>
<p><code>@font-face</code> lets you add a new font family name, and map it to a file that holds a font.</p>
<p>This font will be downloaded by the browser and used in the page, and it’s been such a fundamental change to typography on the web — we can now use any font we want.</p>
<p>We can add <code>@font-face</code> declarations directly into our CSS, or link to a CSS dedicated to importing the font.</p>
<p>In our CSS file we can also use <code>@import</code> to load that CSS file.</p>
<p>A <code>@font-face</code> declaration contains several properties we use to define the font, including <code>src</code>, the URI (one or more URIs) to the font. This follows the same-origin policy, which means fonts can only be downloaded from the current origin (domain + port + protocol).</p>
<p>Fonts are usually in the formats</p>
<ul>
<li><code>woff</code> (Web Open Font Format)</li>
<li><code>woff2</code> (Web Open Font Format 2.0)</li>
<li><code>eot</code> (Embedded Open Type)</li>
<li><code>otf</code> (OpenType Font)</li>
<li><code>ttf</code> (TrueType Font)</li>
</ul>
<p>The following properties allow us to define the properties to the font we are going to load, as we saw above:</p>
<ul>
<li><code>font-family</code></li>
<li><code>font-weight</code></li>
<li><code>font-style</code></li>
<li><code>font-stretch</code></li>
</ul>
<h4 id="heading-a-note-on-performance">A note on performance</h4>
<p>Of course loading a font has performance implications which you must consider when creating the design of your page.</p>
<h3 id="heading-typography">TYPOGRAPHY</h3>
<p>We already talked about fonts, but there’s more to styling text.</p>
<p>In this section we’ll talk about the following properties:</p>
<ul>
<li><code>text-transform</code></li>
<li><code>text-decoration</code></li>
<li><code>text-align</code></li>
<li><code>vertical-align</code></li>
<li><code>line-height</code></li>
<li><code>text-indent</code></li>
<li><code>text-align-last</code></li>
<li><code>word-spacing</code></li>
<li><code>letter-spacing</code></li>
<li><code>text-shadow</code></li>
<li><code>white-space</code></li>
<li><code>tab-size</code></li>
<li><code>writing-mode</code></li>
<li><code>hyphens</code></li>
<li><code>text-orientation</code></li>
<li><code>direction</code></li>
<li><code>line-break</code></li>
<li><code>word-break</code></li>
<li><code>overflow-wrap</code></li>
</ul>
<h4 id="heading-text-transform"><code>text-transform</code></h4>
<p>This property can transform the case of an element.</p>
<p>There are 4 valid values:</p>
<ul>
<li><code>capitalize</code> to uppercase the first letter of each word</li>
<li><code>uppercase</code> to uppercase all the text</li>
<li><code>lowercase</code> to lowercase all the text</li>
<li><code>none</code> to disable transforming the text, used to avoid inheriting the property</li>
</ul>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-transform</span>: uppercase;
}
</code></pre>
<h4 id="heading-text-decoration"><code>text-decoration</code></h4>
<p>This property adds decorations to the text, including</p>
<ul>
<li><code>underline</code></li>
<li><code>overline</code></li>
<li><code>line-through</code></li>
<li><code>blink</code></li>
<li><code>none</code></li>
</ul>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-decoration</span>: underline;
}
</code></pre>
<p>You can also set the style of the decoration, and the color.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-decoration</span>: underline dashed yellow;
}
</code></pre>
<p>Valid style values are <code>solid</code>, <code>double</code>, <code>dotted</code>, <code>dashed</code>, <code>wavy</code>.</p>
<p>You can do all in one line, or use the specific properties:</p>
<ul>
<li><code>text-decoration-line</code></li>
<li><code>text-decoration-color</code></li>
<li><code>text-decoration-style</code></li>
</ul>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-decoration-line</span>: underline;
  <span class="hljs-attribute">text-decoration-color</span>: yellow;
  <span class="hljs-attribute">text-decoration-style</span>: dashed;
}
</code></pre>
<h4 id="heading-text-align"><code>text-align</code></h4>
<p>By default text align has the <code>start</code> value, meaning the text starts at the "start", origin 0, 0 of the box that contains it. This means top left in left-to-right languages, and top right in right-to-left languages.</p>
<p>Possible values are <code>start</code>, <code>end</code>, <code>left</code>, <code>right</code>, <code>center</code>, <code>justify</code> (nice to have a consistent spacing at the line ends):</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-align</span>: right;
}
</code></pre>
<h4 id="heading-vertical-align"><code>vertical-align</code></h4>
<p>Determines how inline elements are vertically aligned.</p>
<p>We have several values for this property. First we can assign a length or percentage value. Those are used to align the text in a position higher or lower (using negative values) than the baseline of the parent element.</p>
<p>Then we have the keywords:</p>
<ul>
<li><code>baseline</code> (the default), aligns the baseline to the baseline of the parent element</li>
<li><code>sub</code> makes an element subscripted, simulating the <code>sub</code> HTML element result</li>
<li><code>super</code> makes an element superscripted, simulating the <code>sup</code> HTML element result</li>
<li><code>top</code> align the top of the element to the top of the line</li>
<li><code>text-top</code> align the top of the element to the top of the parent element font</li>
<li><code>middle</code> align the middle of the element to the middle of the line of the parent</li>
<li><code>bottom</code> align the bottom of the element to the bottom of the line</li>
<li><code>text-bottom</code> align the bottom of the element to the bottom of the parent element font</li>
</ul>
<h4 id="heading-line-height"><code>line-height</code></h4>
<p>This allows you to change the height of a line. Each line of text has a certain font height, but then there is additional spacing vertically between the lines. That’s the line height:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">0.9rem</span>;
}
</code></pre>
<h4 id="heading-text-indent"><code>text-indent</code></h4>
<p>Indent the first line of a paragraph by a set length, or a percentage of the paragraph width:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-indent</span>: -<span class="hljs-number">10px</span>;
}
</code></pre>
<h4 id="heading-text-align-last"><code>text-align-last</code></h4>
<p>By default the last line of a paragraph is aligned following the <code>text-align</code> value. Use this property to change that behavior:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-align-last</span>: right;
}
</code></pre>
<h4 id="heading-word-spacing"><code>word-spacing</code></h4>
<p>Modifies the spacing between each word.</p>
<p>You can use the <code>normal</code> keyword, to reset inherited values, or use a length value:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">word-spacing</span>: <span class="hljs-number">2px</span>;
}

<span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">word-spacing</span>: -<span class="hljs-number">0.2em</span>;
}
</code></pre>
<h4 id="heading-letter-spacing"><code>letter-spacing</code></h4>
<p>Modifies the spacing between each letter.</p>
<p>You can use the <code>normal</code> keyword, to reset inherited values, or use a length value:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">letter-spacing</span>: <span class="hljs-number">0.2px</span>;
}

<span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">letter-spacing</span>: -<span class="hljs-number">0.2em</span>;
}
</code></pre>
<h4 id="heading-text-shadow"><code>text-shadow</code></h4>
<p>Apply a shadow to the text. By default the text has no shadow.</p>
<p>This property accepts an optional color, and a set of values that set</p>
<ul>
<li>the X offset of the shadow from the text</li>
<li>the Y offset of the shadow from the text</li>
<li>the blur radius</li>
</ul>
<p>If the color is not specified, the shadow will use the text color.</p>
<p>Examples:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-shadow</span>: <span class="hljs-number">0.2px</span> <span class="hljs-number">2px</span>;
}

<span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">text-shadow</span>: yellow <span class="hljs-number">0.2px</span> <span class="hljs-number">2px</span> <span class="hljs-number">3px</span>;
}
</code></pre>
<h4 id="heading-white-space"><code>white-space</code></h4>
<p>Sets how CSS handles the white space, new lines and tabs inside an element.</p>
<p>Valid values that collapse white space are:</p>
<ul>
<li><code>normal</code> collapses white space. Adds new lines when necessary as the text reaches the container end</li>
<li><code>nowrap</code> collapses white space. Does not add a new line when the text reaches the end of the container, and suppresses any line break added to the text</li>
<li><code>pre-line</code> collapses white space. Adds new lines when necessary as the text reaches the container end</li>
</ul>
<p>Valid values that preserve white space are:</p>
<ul>
<li><code>pre</code> preserves white space. Does not add a new line when the text reaches the end of the container, but preserves line break added to the text</li>
<li><code>pre-wrap</code> preserves white space. Adds new lines when necessary as the text reaches the container end</li>
</ul>
<h4 id="heading-tab-size"><code>tab-size</code></h4>
<p>Sets the width of the tab character. By default it’s 8, and you can set an integer value that sets the character spaces it takes, or a length value:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">tab-size</span>: <span class="hljs-number">2</span>;
}

<span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">tab-size</span>: <span class="hljs-number">4px</span>;
}
</code></pre>
<h4 id="heading-writing-mode"><code>writing-mode</code></h4>
<p>Defines whether lines of text are laid out horizontally or vertically, and the direction in which blocks progress.</p>
<p>The values you can use are</p>
<ul>
<li><code>horizontal-tb</code> (default)</li>
<li><code>vertical-rl</code> content is laid out vertically. New lines are put on the left of the previous</li>
<li><code>vertical-lr</code> content is laid out vertically. New lines are put on the right of the previous</li>
</ul>
<h4 id="heading-hyphens"><code>hyphens</code></h4>
<p>Determines if hyphens should be automatically added when going to a new line.</p>
<p>Valid values are</p>
<ul>
<li><code>none</code> (default)</li>
<li><code>manual</code> only add an hyphen when there is already a visible hyphen or a hidden hyphen (a special character)</li>
<li><code>auto</code> add hyphens when determined the text can have a hyphen.</li>
</ul>
<h4 id="heading-text-orientation"><code>text-orientation</code></h4>
<p>When <code>writing-mode</code> is in a vertical mode, determines the orientation of the text.</p>
<p>Valid values are</p>
<ul>
<li><code>mixed</code> is the default, and if a language is vertical (like Japanese) it preserves that orientation, while rotating text written in western languages</li>
<li><code>upright</code> makes all text be vertically oriented</li>
<li><code>sideways</code> makes all text horizontally oriented</li>
</ul>
<h4 id="heading-direction"><code>direction</code></h4>
<p>Sets the direction of the text. Valid values are <code>ltr</code> and <code>rtl</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">direction</span>: rtl;
}
</code></pre>
<h4 id="heading-word-break"><code>word-break</code></h4>
<p>This property specifies how to break lines within words.</p>
<ul>
<li><code>normal</code> (default) means the text is only broken between words, not inside a word</li>
<li><code>break-all</code> the browser can break a word (but no hyphens are added)</li>
<li><code>keep-all</code> suppress soft wrapping. Mostly used for CJK (Chinese/Japanese/Korean) text.</li>
</ul>
<p>Speaking of CJK text, the property <code>line-break</code> is used to determine how text lines break. I'm not an expert with those languages, so I will avoid covering it.</p>
<h4 id="heading-overflow-wrap"><code>overflow-wrap</code></h4>
<p>If a word is too long to fit a line, it can overflow outside of the container.</p>
<blockquote>
<p><em>This property is also known as <code>word-wrap</code>, although that is non-standard (but still works as an alias)</em></p>
</blockquote>
<p>This is the default behavior (<code>overflow-wrap: normal;</code>).</p>
<p>We can use:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">overflow-wrap</span>: break-word;
}
</code></pre>
<p>to break it at the exact length of the line, or</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">overflow-wrap</span>: anywhere;
}
</code></pre>
<p>if the browser sees there’s a soft wrap opportunity somewhere earlier. No hyphens are added, in any case.</p>
<p>This property is very similar to <code>word-break</code>. We might want to choose this one on western languages, while <code>word-break</code> has special treatment for non-western languages.</p>
<h3 id="heading-box-model">BOX MODEL</h3>
<p>Every CSS element is essentially a box. Every element is a generic box.</p>
<p>The box model explains the sizing of the elements based on a few CSS properties.</p>
<p>From the inside to the outside, we have:</p>
<ul>
<li>the content area</li>
<li>padding</li>
<li>border</li>
<li>margin</li>
</ul>
<p>The best way to visualize the box model is to open the browser DevTools and check how it is displayed:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xj9Q5XeqWTDKdl2roL0mkiHGXxRfGnAs4MhI" alt="Image" width="800" height="463" loading="lazy"></p>
<p>Here you can see how Firefox tells me the properties of a <code>span</code> element I highlighted. I right-clicked on it, pressed Inspect Element, and went to the Layout panel of the DevTools.</p>
<p>See, the light blue space is the content area. Surrounding it there is the padding, then the border and finally the margin.</p>
<p>By default, if you set a width (or height) on the element, that is going to be applied to the <strong>content area</strong>. All the padding, border, and margin calculations are done outside of the value, so you have to keep this in mind when you do your calculation.</p>
<p>Later you’ll see how you can change this behavior using Box Sizing.</p>
<h3 id="heading-border">BORDER</h3>
<p>The border is a thin layer between padding and margin. By editing the border, you can make elements draw their perimeter on screen.</p>
<p>You can work on borders by using those properties:</p>
<ul>
<li><code>border-style</code></li>
<li><code>border-color</code></li>
<li><code>border-width</code></li>
</ul>
<p>The property <code>border</code> can be used as a shorthand for all those properties.</p>
<p><code>border-radius</code> is used to create rounded corners.</p>
<p>You also have the ability to use images as borders, an ability given to you by <code>border-image</code> and its specific separate properties:</p>
<ul>
<li><code>border-image-source</code></li>
<li><code>border-image-slice</code></li>
<li><code>border-image-width</code></li>
<li><code>border-image-outset</code></li>
<li><code>border-image-repeat</code></li>
</ul>
<p>Let’s start with <code>border-style</code>.</p>
<h4 id="heading-the-border-style">The border style</h4>
<p>The <code>border-style</code> property lets you choose the style of the border. The options you can use are:</p>
<ul>
<li><code>dotted</code></li>
<li><code>dashed</code></li>
<li><code>solid</code></li>
<li><code>double</code></li>
<li><code>groove</code></li>
<li><code>ridge</code></li>
<li><code>inset</code></li>
<li><code>outset</code></li>
<li><code>none</code></li>
<li><code>hidden</code></li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/lCWsi0wfQU30QoiDD6GsvfRrWx-4DurGOMeX" alt="Image" width="426" height="459" loading="lazy"></p>
<p>Check out <a target="_blank" href="https://codepen.io/flaviocopes/pen/yraaxq">this Codepen</a> for a live example.</p>
<p>The default for the style is <code>none</code>, so to make the border appear at all you need to change it to something else. <code>solid</code> is a good choice most of the time.</p>
<p>You can set a different style for each edge using the properties</p>
<ul>
<li><code>border-top-style</code></li>
<li><code>border-right-style</code></li>
<li><code>border-bottom-style</code></li>
<li><code>border-left-style</code></li>
</ul>
<p>or you can use <code>border-style</code> with multiple values to define them, using the usual Top-Right-Bottom-Left order:</p>
<pre><code>p {
  border-style: solid dotted solid dotted;
}
</code></pre><h4 id="heading-the-border-width">The border width</h4>
<p><code>border-width</code> is used to set the width of the border.</p>
<p>You can use one of the pre-defined values:</p>
<ul>
<li><code>thin</code></li>
<li><code>medium</code> (the default value)</li>
<li><code>thick</code></li>
</ul>
<p>or express a value in pixels, em or rem or any other valid length value.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">border-width</span>: <span class="hljs-number">2px</span>;
}
</code></pre>
<p>You can set the width of each edge (Top-Right-Bottom-Left) separately by using 4 values:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">border-width</span>: <span class="hljs-number">2px</span> <span class="hljs-number">1px</span> <span class="hljs-number">2px</span> <span class="hljs-number">1px</span>;
}
</code></pre>
<p>or you can use the specific edge properties <code>border-top-width</code>, <code>border-right-width</code>, <code>border-bottom-width</code>, <code>border-left-width</code>.</p>
<h4 id="heading-the-border-color">The border color</h4>
<p><code>border-color</code> is used to set the color of the border.</p>
<p>If you don’t set a color, the border by default is colored using the color of the text in the element.</p>
<p>You can pass any valid color value to <code>border-color</code>.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">border-color</span>: yellow;
}
</code></pre>
<p>You can set the color of each edge (Top-Right-Bottom-Left) separately by using 4 values:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">border-color</span>: black red yellow blue;
}
</code></pre>
<p>or you can use the specific edge properties <code>border-top-color</code>, <code>border-right-color</code>, <code>border-bottom-color</code>, <code>border-left-color</code>.</p>
<h4 id="heading-the-border-shorthand-property">The border shorthand property</h4>
<p>Those 3 properties mentioned, <code>border-width</code>, <code>border-style</code> and <code>border-color</code> can be set using the shorthand property <code>border</code>.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> black solid;
}
</code></pre>
<p>You can also use the edge-specific properties <code>border-top</code>, <code>border-right</code>, <code>border-bottom</code>, <code>border-left</code>.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">border-left</span>: <span class="hljs-number">2px</span> black solid;
  <span class="hljs-attribute">border-right</span>: <span class="hljs-number">3px</span> red dashed;
}
</code></pre>
<h4 id="heading-the-border-radius">The border radius</h4>
<p><code>border-radius</code> is used to set rounded corners to the border. You need to pass a value that will be used as the radius of the circle that will be used to round the border.</p>
<p>Usage:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">3px</span>;
}
</code></pre>
<p>You can also use the edge-specific properties <code>border-top-left-radius</code>, <code>border-top-right-radius</code>, <code>border-bottom-left-radius</code>, <code>border-bottom-right-radius</code>.</p>
<h4 id="heading-using-images-as-borders">Using images as borders</h4>
<p>One very cool thing with borders is the ability to use images to style them. This lets you go very creative with borders.</p>
<p>We have 5 properties:</p>
<ul>
<li><code>border-image-source</code></li>
<li><code>border-image-slice</code></li>
<li><code>border-image-width</code></li>
<li><code>border-image-outset</code></li>
<li><code>border-image-repeat</code></li>
</ul>
<p>and the shorthand <code>border-image</code>. I won't go in much details here as images as borders would need a more in-depth coverage as what I can do in this little chapter. I recommend reading the <a target="_blank" href="https://css-tricks.com/almanac/properties/b/border-image/">CSS Tricks almanac entry on border-image</a> for more information.</p>
<h3 id="heading-padding">PADDING</h3>
<p>The <code>padding</code> CSS property is commonly used in CSS to add space in the inner side of an element.</p>
<p>Remember:</p>
<ul>
<li><code>margin</code> adds space outside an element border</li>
<li><code>padding</code> adds space inside an element border</li>
</ul>
<h4 id="heading-specific-padding-properties">Specific padding properties</h4>
<p><code>padding</code> has 4 related properties that alter the padding of a single edge at once:</p>
<ul>
<li><code>padding-top</code></li>
<li><code>padding-right</code></li>
<li><code>padding-bottom</code></li>
<li><code>padding-left</code></li>
</ul>
<p>The usage of those is very simple and cannot be confused, for example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">padding-left</span>: 30<span class="hljs-selector-tag">px</span>;
<span class="hljs-selector-tag">padding-right</span>: 3<span class="hljs-selector-tag">em</span>;
</code></pre>
<h4 id="heading-using-the-padding-shorthand">Using the <code>padding</code> shorthand</h4>
<p><code>padding</code> is a shorthand to specify multiple padding values at the same time, and depending on the number of values entered, it behaves differently.</p>
<h4 id="heading-1-value">1 value</h4>
<p>Using a single value applies that to <strong>all</strong> the paddings: top, right, bottom, left.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">padding</span>: 20<span class="hljs-selector-tag">px</span>;
</code></pre>
<h4 id="heading-2-values">2 values</h4>
<p>Using 2 values applies the first to <strong>bottom &amp; top</strong>, and the second to <strong>left &amp; right</strong>.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">padding</span>: 20<span class="hljs-selector-tag">px</span> 10<span class="hljs-selector-tag">px</span>;
</code></pre>
<h4 id="heading-3-values">3 values</h4>
<p>Using 3 values applies the first to <strong>top</strong>, the second to <strong>left &amp; right</strong>, the third to <strong>bottom</strong>.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">padding</span>: 20<span class="hljs-selector-tag">px</span> 10<span class="hljs-selector-tag">px</span> 30<span class="hljs-selector-tag">px</span>;
</code></pre>
<h4 id="heading-4-values">4 values</h4>
<p>Using 4 values applies the first to <strong>top</strong>, the second to <strong>right</strong>, the third to <strong>bottom</strong>, the fourth to <strong>left</strong>.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">padding</span>: 20<span class="hljs-selector-tag">px</span> 10<span class="hljs-selector-tag">px</span> 5<span class="hljs-selector-tag">px</span> 0<span class="hljs-selector-tag">px</span>;
</code></pre>
<p>So, the order is <em>top-right-bottom-left</em>.</p>
<h4 id="heading-values-accepted">Values accepted</h4>
<p><code>padding</code> accepts values expressed in any kind of length unit, the most common ones are px, em, rem, but <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/length">many others exist</a>.</p>
<h3 id="heading-margin">MARGIN</h3>
<p>The <code>margin</code> CSS property is commonly used in CSS to add space around an element.</p>
<p>Remember:</p>
<ul>
<li><code>margin</code> adds space outside an element border</li>
<li><code>padding</code> adds space inside an element border</li>
</ul>
<h4 id="heading-specific-margin-properties">Specific margin properties</h4>
<p><code>margin</code> has 4 related properties that alter the margin of a single edge at once:</p>
<ul>
<li><code>margin-top</code></li>
<li><code>margin-right</code></li>
<li><code>margin-bottom</code></li>
<li><code>margin-left</code></li>
</ul>
<p>The usage of those is very simple and cannot be confused, for example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">margin-left</span>: 30<span class="hljs-selector-tag">px</span>;
<span class="hljs-selector-tag">margin-right</span>: 3<span class="hljs-selector-tag">em</span>;
</code></pre>
<h4 id="heading-using-the-margin-shorthand">Using the <code>margin</code> shorthand</h4>
<p><code>margin</code> is a shorthand to specify multiple margins at the same time, and depending on the number of values entered, it behaves differently.</p>
<h4 id="heading-1-value-1">1 value</h4>
<p>Using a single value applies that to <strong>all</strong> the margins: top, right, bottom, left.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">margin</span>: 20<span class="hljs-selector-tag">px</span>;
</code></pre>
<h4 id="heading-2-values-1">2 values</h4>
<p>Using 2 values applies the first to <strong>bottom &amp; top</strong>, and the second to <strong>left &amp; right</strong>.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">margin</span>: 20<span class="hljs-selector-tag">px</span> 10<span class="hljs-selector-tag">px</span>;
</code></pre>
<h4 id="heading-3-values-1">3 values</h4>
<p>Using 3 values applies the first to <strong>top</strong>, the second to <strong>left &amp; right</strong>, the third to <strong>bottom</strong>.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">margin</span>: 20<span class="hljs-selector-tag">px</span> 10<span class="hljs-selector-tag">px</span> 30<span class="hljs-selector-tag">px</span>;
</code></pre>
<h4 id="heading-4-values-1">4 values</h4>
<p>Using 4 values applies the first to <strong>top</strong>, the second to <strong>right</strong>, the third to <strong>bottom</strong>, the fourth to <strong>left</strong>.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">margin</span>: 20<span class="hljs-selector-tag">px</span> 10<span class="hljs-selector-tag">px</span> 5<span class="hljs-selector-tag">px</span> 0<span class="hljs-selector-tag">px</span>;
</code></pre>
<p>So, the order is <em>top-right-bottom-left</em>.</p>
<h4 id="heading-values-accepted-1">Values accepted</h4>
<p><code>margin</code> accepts values expressed in any kind of length unit, the most common ones are px, em, rem, but <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/length">many others exist</a>.</p>
<p>It also accepts percentage values, and the special value <code>auto</code>.</p>
<h4 id="heading-using-auto-to-center-elements">Using <code>auto</code> to center elements</h4>
<p><code>auto</code> can be used to tell the browser to select automatically a margin, and it's most commonly used to center an element in this way:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">margin</span>: 0 <span class="hljs-selector-tag">auto</span>;
</code></pre>
<p>As said above, using 2 values applies the first to <strong>bottom &amp; top</strong>, and the second to <strong>left &amp; right</strong>.</p>
<p>The modern way to center elements is to use <a target="_blank" href="https://flaviocopes.com/flexbox/">Flexbox</a>, and its <code>justify-content: center;</code> directive.</p>
<p>Older browsers of course do not implement Flexbox, and if you need to support them <code>margin: 0 auto;</code> is still a good choice.</p>
<h4 id="heading-using-a-negative-margin">Using a negative margin</h4>
<p><code>margin</code> is the only property related to sizing that can have a negative value. It's extremely useful, too. Setting a negative top margin makes an element move over elements before it, and given enough negative value it will move out of the page.</p>
<p>A negative bottom margin moves up the elements after it.</p>
<p>A negative right margin makes the content of the element expand beyond its allowed content size.</p>
<p>A negative left margin moves the element left over the elements that precede it, and given enough negative value it will move out of the page.</p>
<h3 id="heading-box-sizing">BOX SIZING</h3>
<p>The default behavior of browsers when calculating the width of an element is to apply the calculated width and height to the <strong>content area</strong>, without taking any of the padding, border and margin in consideration.</p>
<p>This approach has proven to be quite complicated to work with.</p>
<p>You can change this behavior by setting the <code>box-sizing</code> property.</p>
<p>The <code>box-sizing</code> property is a great help. It has 2 values:</p>
<ul>
<li><code>border-box</code></li>
<li><code>content-box</code></li>
</ul>
<p><code>content-box</code> is the default, the one we had for ages before <code>box-sizing</code> became a thing.</p>
<p><code>border-box</code> is the new and great thing we are looking for. If you set that on an element:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.my-div</span> {
  <span class="hljs-attribute">box-sizing</span>: border-box;
}
</code></pre>
<p>width and height calculation include the padding and the border. Only the margin is left out, which is reasonable since in our mind we also typically see that as a separate thing: margin is outside of the box.</p>
<p>This property is a small change but has a big impact. CSS Tricks even declared an <a target="_blank" href="https://css-tricks.com/international-box-sizing-awareness-day/">international box-sizing awareness day</a>, just saying, and it’s recommended to apply it to every element on the page, out of the box, with this:</p>
<pre><code class="lang-css">*, *<span class="hljs-selector-pseudo">:before</span>, *<span class="hljs-selector-pseudo">:after</span> {
  <span class="hljs-attribute">box-sizing</span>: border-box;
}
</code></pre>
<h3 id="heading-display">DISPLAY</h3>
<p>The <code>display</code> property of an object determines how it is rendered by the browser.</p>
<p>It’s a very important property, and probably the one with the highest number of values you can use.</p>
<p>Those values include:</p>
<ul>
<li><code>block</code></li>
<li><code>inline</code></li>
<li><code>none</code></li>
<li><code>contents</code></li>
<li><code>flow</code></li>
<li><code>flow-root</code></li>
<li><code>table</code> (and all the <code>table-*</code> ones)</li>
<li><code>flex</code></li>
<li><code>grid</code></li>
<li><code>list-item</code></li>
<li><code>inline-block</code></li>
<li><code>inline-table</code></li>
<li><code>inline-flex</code></li>
<li><code>inline-grid</code></li>
<li><code>inline-list-item</code></li>
</ul>
<p>plus others you will not likely use, like <code>ruby</code>.</p>
<p>Choosing any of those will considerably alter the behavior of the browser with the element and its children.</p>
<p>In this section we’ll analyze the most important ones not covered elsewhere:</p>
<ul>
<li><code>block</code></li>
<li><code>inline</code></li>
<li><code>inline-block</code></li>
<li><code>none</code></li>
</ul>
<p>We’ll see some of the others in later chapters, including coverage of <code>table</code>, <code>flex</code> and <code>grid</code>.</p>
<h4 id="heading-inline"><code>inline</code></h4>
<p>Inline is the default display value for every element in CSS.</p>
<p>All the HTML tags are displayed inline out of the box except some elements like <code>div</code>, <code>p</code> and <code>section</code>, which are set as <code>block</code> by the user agent (the browser).</p>
<p>Inline elements don’t have any margin or padding applied.</p>
<p>Same for height and width.</p>
<p>You <em>can</em> add them, but the appearance in the page won’t change — they are calculated and applied automatically by the browser.</p>
<h4 id="heading-inline-block"><code>inline-block</code></h4>
<p>Similar to <code>inline</code>, but with <code>inline-block</code> <code>width</code> and <code>height</code> applied as you specify.</p>
<h4 id="heading-block"><code>block</code></h4>
<p>As mentioned, normally elements are displayed inline, with the exception of some elements, including</p>
<ul>
<li><code>div</code></li>
<li><code>p</code></li>
<li><code>section</code></li>
<li><code>ul</code></li>
</ul>
<p>which are set as <code>block</code> by the browser.</p>
<p>With <code>display: block</code>, elements are stacked one after each other, vertically, and every element takes up 100% of the page.</p>
<p>The values assigned to the <code>width</code> and <code>height</code> properties are respected, if you set them, along with <code>margin</code> and <code>padding</code>.</p>
<h4 id="heading-none"><code>none</code></h4>
<p>Using <code>display: none</code> makes an element disappear. It's still there in the HTML, but just not visible in the browser.</p>
<h3 id="heading-positioning">POSITIONING</h3>
<p>Positioning is what makes us determine where elements appear on the screen, and how they appear.</p>
<p>You can move elements around, and position them exactly where you want.</p>
<p>In this section we’ll also see how things change on a page based on how elements with different <code>position</code> interact with each other.</p>
<p>We have one main CSS property: <code>position</code>.</p>
<p>It can have those 5 values:</p>
<ul>
<li><code>static</code></li>
<li><code>relative</code></li>
<li><code>absolute</code></li>
<li><code>fixed</code></li>
<li><code>sticky</code></li>
</ul>
<h4 id="heading-static-positioning">Static positioning</h4>
<p>This is the default value for an element. Static positioned elements are displayed in the normal page flow.</p>
<h4 id="heading-relative-positioning">Relative positioning</h4>
<p>If you set <code>position: relative</code> on an element, you are now able to position it with an offset, using the properties</p>
<ul>
<li>top</li>
<li>right</li>
<li>bottom</li>
<li>left</li>
</ul>
<p>which are called <strong>offset properties</strong>. They accept a length value or a percentage.</p>
<p>Take <a target="_blank" href="https://codepen.io/flaviocopes/pen/WWGgrR">this example I made on Codepen</a>. I create a parent container, a child container, and an inner box with some text:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"parent"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"child"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"box"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Test<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>with some CSS to give some colors and padding, but does not affect positioning:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.parent</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#af47ff</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
}

<span class="hljs-selector-class">.child</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#ff4797</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span>;
}

<span class="hljs-selector-class">.box</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f3ff47</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid <span class="hljs-number">#333</span>;
  <span class="hljs-attribute">border-style</span>: dotted;
  <span class="hljs-attribute">font-family</span>: courier;
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
}
</code></pre>
<p>here’s the result:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/gtXUfjyrczqxDqdfrjJyec58o9ru6CqGGCFD" alt="Image" width="379" height="297" loading="lazy"></p>
<p>You can try and add any of the properties I mentioned before (<code>top</code>, <code>right</code>, <code>bottom</code>, <code>left</code>) to <code>.box</code>, and nothing will happen. The position is <code>static</code>.</p>
<p>Now if we set <code>position: relative</code> to the box, at first apparently nothing changes. But the element is now able to move using the <code>top</code>, <code>right</code>, <code>bottom</code>, <code>left</code> properties, and now you can alter the position of it relatively to the element containing it.</p>
<p>For example:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.box</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">top</span>: -<span class="hljs-number">60px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/aYTcDVhCB9-CazlQrWrPyfxMpr3TThT0V-ho" alt="Image" width="386" height="303" loading="lazy"></p>
<p>A negative value for <code>top</code> will make the box move up relatively to its container.</p>
<p>Or</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.box</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">top</span>: -<span class="hljs-number">60px</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">180px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/5ePc6ALKZV0fubpagz0OzfPBCzctqPAJY81p" alt="Image" width="508" height="299" loading="lazy"></p>
<p>Notice how the space that is occupied by the box remains preserved in the container, like it was still in its place.</p>
<p>Another property that will now work is <code>z-index</code> to alter the z-axis placement. We'll talk about it later on.</p>
<h4 id="heading-absolute-positioning">Absolute positioning</h4>
<p>Setting <code>position: absolute</code> on an element will remove it from the document's flow.</p>
<p>Remember in relative positioning that we noticed the space originally occupied by an element was preserved even if it was moved around?</p>
<p>With absolute positioning, as soon as we set <code>position: absolute</code> on <code>.box</code>, its original space is now collapsed, and only the origin (x, y coordinates) remain the same.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.box</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: absolute;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/B4aFUpYab0eSO-LUQKAu2Vmbi-wnFA8qFOHm" alt="Image" width="381" height="251" loading="lazy"></p>
<p>We can now move the box around as we please, using the <code>top</code>, <code>right</code>, <code>bottom</code>, <code>left</code> properties:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.box</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">0px</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">0px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/NHw-ZkR2lzBsPyb9gSYTyuYGreSvedNPsJ7J" alt="Image" width="419" height="204" loading="lazy"></p>
<p>or</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.box</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">140px</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">50px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/QOYrWkDjiNv7ODZ9WtYCBVEnJf5oZwGfombH" alt="Image" width="388" height="320" loading="lazy"></p>
<p>The coordinates are relative to the closest container that is not <code>static</code>.</p>
<p>This means that if we add <code>position: relative</code> to the <code>.child</code> element, and we set <code>top</code> and <code>left</code> to 0, the box will not be positioned at the top left margin of the <em>window</em>, but rather it will be positioned at the 0, 0 coordinates of <code>.child</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.child</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: relative;
}

<span class="hljs-selector-class">.box</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">0px</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">0px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1FB8qKtiZgmxtp7xjd6UU7CW573XRxTrZlNc" alt="Image" width="419" height="211" loading="lazy"></p>
<p>Here’s how we already saw that <code>.child</code> is static (the default):</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.child</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: static;
}

<span class="hljs-selector-class">.box</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">0px</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">0px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/eF4yC5dRIkcyezTcVUCbG36sfxOVurQX2L38" alt="Image" width="419" height="204" loading="lazy"></p>
<p>Like for relative positioning, you can use <code>z-index</code> to alter the z-axis placement.</p>
<h4 id="heading-fixed-positioning">Fixed positioning</h4>
<p>Like with absolute positioning, when an element is assigned <code>position: fixed</code> it's removed from the flow of the page.</p>
<p>The difference with absolute positioning is this: elements are now always positioned relative to the window, instead of the first non-static container.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.box</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: fixed;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Ium4uJdPRXPpp-gAVsMMWveviu6HY-g0nUYA" alt="Image" width="381" height="240" loading="lazy"></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.box</span> {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-attribute">position</span>: fixed;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/k3-LecCC6WXUjssKdQ9u9w70EZSh3hzK3iFY" alt="Image" width="395" height="179" loading="lazy"></p>
<p>Another big difference is that elements are not affected by scrolling. Once you put a fixed element somewhere, scrolling the page does not remove it from the visible part of the page.</p>
<h4 id="heading-sticky-positioning">Sticky positioning</h4>
<p>While the above values have been around for a very long time, this one was introduced recently and it’s still relatively unsupported (<a target="_blank" href="https://caniuse.com/#feat=css-sticky">see caniuse.com</a>)</p>
<p>The UITableView iOS component is the thing that comes to mind when I think about <code>position: sticky</code>. You know when you scroll in the contacts list and the first letter is stuck to the top, to let you know you are viewing that particular letter's contacts?</p>
<p>We used JavaScript to emulate that, but this is the approach taken by CSS to allow it natively.</p>
<h3 id="heading-floating-and-clearing">FLOATING AND CLEARING</h3>
<p>Floating has been a very important topic in the past.</p>
<p>It was used in lots of hacks and creative usages because it was one of the few ways, along with tables, we could really implement some layouts. In the past we used to float the sidebar to the left, for example, to show it on the left side of the screen and added some margin to the main content.</p>
<p>Luckily times have changed and today we have Flexbox and Grid to help us with layout, and float has gone back to its original scope: placing content on one side of the container element, and making its siblings show up around it.</p>
<p>The <code>float</code> property supports 3 values:</p>
<ul>
<li><code>left</code></li>
<li><code>right</code></li>
<li><code>none</code> (the default)</li>
</ul>
<p>Say we have a box which contains a paragraph with some text, and the paragraph also contains an image.</p>
<p>Here’s some code:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">parent</span>"&gt;
  &lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">child</span>"&gt;
    &lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">box</span>"&gt;
      &lt;<span class="hljs-selector-tag">p</span>&gt;<span class="hljs-selector-tag">This</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">some</span> <span class="hljs-selector-tag">random</span> <span class="hljs-selector-tag">paragraph</span> <span class="hljs-selector-tag">and</span> <span class="hljs-selector-tag">an</span> <span class="hljs-selector-tag">image</span>. &lt;<span class="hljs-selector-tag">img</span> <span class="hljs-selector-tag">src</span>="<span class="hljs-selector-tag">https</span>://<span class="hljs-selector-tag">via</span><span class="hljs-selector-class">.placeholder</span><span class="hljs-selector-class">.com</span>/100<span class="hljs-selector-tag">x100</span>" /&gt; <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>.
      &lt;/<span class="hljs-selector-tag">p</span>&gt;
    &lt;/<span class="hljs-selector-tag">div</span>&gt;
  &lt;/<span class="hljs-selector-tag">div</span>&gt;
&lt;/<span class="hljs-selector-tag">div</span>&gt;

<span class="hljs-selector-class">.parent</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#af47ff</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">500px</span>;
}

<span class="hljs-selector-class">.child</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#ff4797</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span>;
}

<span class="hljs-selector-class">.box</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f3ff47</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid <span class="hljs-number">#333</span>;
  <span class="hljs-attribute">border-style</span>: dotted;
  <span class="hljs-attribute">font-family</span>: courier;
  <span class="hljs-attribute">text-align</span>: justify;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1rem</span>;
}
</code></pre>
<p>and the visual appearance:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/fx5ZaCoCalyWSNeIkNi6044e5uEPPlQVupJD" alt="Image" width="578" height="507" loading="lazy"></p>
<p>As you can see, the normal flow by default considers the image inline, and makes space for it in the line itself.</p>
<p>If we add <code>float: left</code> to the image, and some padding:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">float</span>: left;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span> <span class="hljs-number">20px</span> <span class="hljs-number">0px</span> <span class="hljs-number">0px</span>;
}
</code></pre>
<p>this is the result:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Yftt6zI7UBrNYY30BapoEr3BAtiVCx80M4Eq" alt="Image" width="584" height="465" loading="lazy"></p>
<p>and this is what we get by applying a float: right, adjusting the padding accordingly:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">float</span>: right;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span> <span class="hljs-number">0px</span> <span class="hljs-number">20px</span> <span class="hljs-number">20px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/WORQNScMck67c42LH0cfbiZJmzNnGzWde1Au" alt="Image" width="583" height="478" loading="lazy"></p>
<p>A floated element is removed from the normal flow of the page, and the other content flows around it.</p>
<p><a target="_blank" href="https://codepen.io/flaviocopes/pen/WWGqPr?editors=1100">See the example on Codepen</a></p>
<p>You are not limited to floating images, too. Here we switch the image with a <code>span</code> element:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">parent</span>"&gt;
  &lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">child</span>"&gt;
    &lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">box</span>"&gt;
      &lt;<span class="hljs-selector-tag">p</span>&gt;<span class="hljs-selector-tag">This</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">some</span> <span class="hljs-selector-tag">random</span> <span class="hljs-selector-tag">paragraph</span> <span class="hljs-selector-tag">and</span> <span class="hljs-selector-tag">an</span> <span class="hljs-selector-tag">image</span>. &lt;<span class="hljs-selector-tag">span</span>&gt;<span class="hljs-selector-tag">Some</span> <span class="hljs-selector-tag">text</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">float</span>&lt;/<span class="hljs-selector-tag">span</span>&gt; <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>. <span class="hljs-selector-tag">The</span> <span class="hljs-selector-tag">image</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">middle</span> <span class="hljs-selector-tag">of</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">text</span>.
      &lt;/<span class="hljs-selector-tag">p</span>&gt;
    &lt;/<span class="hljs-selector-tag">div</span>&gt;
  &lt;/<span class="hljs-selector-tag">div</span>&gt;
&lt;/<span class="hljs-selector-tag">div</span>&gt;

<span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">float</span>: right;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">20px</span> <span class="hljs-number">0px</span> <span class="hljs-number">20px</span> <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid black
}
</code></pre>
<p>and this is the result:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Pe0oVfgmeHF7Rheb4hPwXTaq5AZ1939rMeBy" alt="Image" width="579" height="476" loading="lazy"></p>
<h4 id="heading-clearing">Clearing</h4>
<p>What happens when you float more than one element?</p>
<p>If when floated they find another floated image, by default they are stacked up one next to the other, horizontally. Until there is no room, and they will start being stacked on a new line.</p>
<p>Say we had 3 inline images inside a <code>p</code> tag:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/15-LCn0BOSVAVMraLSiNzWpP-oWBiEKIGULW" alt="Image" width="580" height="594" loading="lazy"></p>
<p>If we add <code>float: left</code> to those images:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">float</span>: left;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span> <span class="hljs-number">20px</span> <span class="hljs-number">0px</span> <span class="hljs-number">0px</span>;
}
</code></pre>
<p>this is what we’ll have:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JGZ7LTxKux1nKWIISdzIPgb2jzxcqpifbxIx" alt="Image" width="577" height="610" loading="lazy"></p>
<p>if you add <code>clear: left</code> to images, those are going to be stacked vertically rather than horizontally:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/9J-ggQAlJFZ4C1hUbnpD74FcjuKpS960LABv" alt="Image" width="578" height="594" loading="lazy"></p>
<p>I used the <code>left</code> value for <code>clear</code>. It allows</p>
<ul>
<li><code>left</code> to clear left floats</li>
<li><code>right</code> to clear right floats</li>
<li><code>both</code> to clear both left and right floats</li>
<li><code>none</code> (default) disables clearing</li>
</ul>
<h3 id="heading-z-index">Z-INDEX</h3>
<p>When we talked about positioning, I mentioned that you can use the <code>z-index</code> property to control the Z axis positioning of elements.</p>
<p>It’s very useful when you have multiple elements that overlap each other, and you need to decide which one is visible, as nearer to the user, and which one(s) should be hidden behind it.</p>
<p>This property takes a number (without decimals) and uses that number to calculate which elements appear nearer to the user, in the Z axis.</p>
<p>The higher the z-index value, the more an element is positioned nearer to the user.</p>
<p>When deciding which element should be visible and which one should be positioned behind it, the browser does a calculation on the z-index value.</p>
<p>The default value is <code>auto</code>, a special keyword. Using <code>auto</code>, the Z axis order is determined by the position of the HTML element in the page - the last sibling appears first, as it's defined last.</p>
<p>By default elements have the <code>static</code> value for the <code>position</code> property. In this case, the <code>z-index</code> property does not make any difference - it must be set to <code>absolute</code>, <code>relative</code> or <code>fixed</code> to work.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.my-first-div</span> {
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">600px</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">600px</span>;
    <span class="hljs-attribute">z-index</span>: <span class="hljs-number">10</span>;
}

<span class="hljs-selector-class">.my-second-div</span> {
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">500px</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">500px</span>;
    <span class="hljs-attribute">z-index</span>: <span class="hljs-number">20</span>;
}
</code></pre>
<p>The element with class <code>.my-second-div</code> will be displayed, and behind it <code>.my-first-div</code>.</p>
<p>Here we used 10 and 20, but you can use any number. Negative numbers too. It’s common to pick non-consecutive numbers, so you can position elements in the middle. If you use consecutive numbers instead, you would need to re-calculate the z-index of each element involved in the positioning.</p>
<h3 id="heading-css-grid">CSS GRID</h3>
<p>CSS Grid is the new kid in the CSS town, and while not yet fully supported by all browsers, it’s going to be the future system for layouts.</p>
<p>CSS Grid is a fundamentally new approach to building layouts using CSS.</p>
<p>Keep an eye on the CSS Grid Layout page on caniuse.com (<a target="_blank" href="https://caniuse.com/#feat=css-grid">https://caniuse.com/#feat=css-grid</a>) to find out which browsers currently support it. At the time of writing, April 2019, all major browsers (except IE, which will never have support for it) are already supporting this technology, covering 92% of all users.</p>
<p>CSS Grid is not a competitor to Flexbox. They interoperate and collaborate on complex layouts, because CSS Grid works on 2 dimensions (rows AND columns) while Flexbox works on a single dimension (rows OR columns).</p>
<p>Building layouts for the web has traditionally been a complicated topic.</p>
<p>I won’t dig into the reasons for this complexity, which is a complex topic on its own. But you can think yourself as a very lucky human because nowadays you have 2 very powerful and well supported tools at your disposal:</p>
<ul>
<li><strong>CSS Flexbox</strong></li>
<li><strong>CSS Grid</strong></li>
</ul>
<p>These 2 are the tools to build the Web layouts of the future.</p>
<p>Unless you need to support old browsers like IE8 and IE9, there is no reason to be messing with things like:</p>
<ul>
<li>Table layouts</li>
<li>Floats</li>
<li>clearfix hacks</li>
<li><code>display: table</code> hacks</li>
</ul>
<p>In this guide there’s all you need to know about going from zero knowledge of CSS Grid to being a proficient user.</p>
<h4 id="heading-the-basics">The basics</h4>
<p>The CSS Grid layout is activated on a container element (which can be a <code>div</code> or any other tag) by setting <code>display: grid</code>.</p>
<p>As with flexbox, you can define some properties on the container, and some properties on each individual item in the grid.</p>
<p>These properties combined will determine the final look of the grid.</p>
<p>The most basic container properties are <code>grid-template-columns</code> and <code>grid-template-rows</code>.</p>
<h4 id="heading-grid-template-columns-and-grid-template-rows">grid-template-columns and grid-template-rows</h4>
<p>Those properties define the number of columns and rows in the grid, and they also set the width of each column/row.</p>
<p>The following snippet defines a grid with 4 columns each 200px wide, and 2 rows with a 300px height each.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">300px</span> <span class="hljs-number">300px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/LgbgchKoiffQNAqLtBYVbPsLJMKiWB3XWvCP" alt="Image" width="728" height="633" loading="lazy"></p>
<p>Here’s another example of a grid with 2 columns and 2 rows:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">200px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">100px</span> <span class="hljs-number">100px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/sdVnLwfTJmY1alewU41wNxRMZ827XK07quWq" alt="Image" width="696" height="391" loading="lazy"></p>
<h4 id="heading-automatic-dimensions">Automatic dimensions</h4>
<p>Many times you might have a fixed header size, a fixed footer size, and the main content that is flexible in height, depending on its length. In this case you can use the auto keyword:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">100px</span> auto <span class="hljs-number">100px</span>;
}
</code></pre>
<h4 id="heading-different-columns-and-rows-dimensions">Different columns and rows dimensions</h4>
<p>In the above examples we made regular grids by using the same values for rows and the same values for columns.</p>
<p>You can specify any value for each row/column, to create a lot of different designs:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">100px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">100px</span> <span class="hljs-number">50px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/h5vifpz6IUZQbWCzX4YvJjOhLojgzgP2F-AN" alt="Image" width="597" height="358" loading="lazy"></p>
<p>Another example:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">10px</span> <span class="hljs-number">100px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">100px</span> <span class="hljs-number">10px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/GGCFboj9Z6YQz8jvB69KmslqKz00sLuca843" alt="Image" width="581" height="609" loading="lazy"></p>
<h4 id="heading-adding-space-between-the-cells">Adding space between the cells</h4>
<p>Unless specified, there is no space between the cells.</p>
<p>You can add spacing by using those properties:</p>
<ul>
<li><code>grid-column-gap</code></li>
<li><code>grid-row-gap</code></li>
</ul>
<p>or the shorthand syntax <code>grid-gap</code>.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">100px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">100px</span> <span class="hljs-number">50px</span>;
  <span class="hljs-attribute">grid-column-gap</span>: <span class="hljs-number">25px</span>;
  <span class="hljs-attribute">grid-row-gap</span>: <span class="hljs-number">25px</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ivVtIubdZG3BpFfoASpFy4EMJG1kXeiCx3zP" alt="Image" width="642" height="412" loading="lazy"></p>
<p>The same layout using the shorthand:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">100px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">100px</span> <span class="hljs-number">50px</span>;
  <span class="hljs-attribute">grid-gap</span>: <span class="hljs-number">25px</span>;
}
</code></pre>
<h4 id="heading-spanning-items-on-multiple-columns-andor-rows">Spanning items on multiple columns and/or rows</h4>
<p>Every cell item has the option to occupy more than just one box in the row, and expand horizontally or vertically to get more space, while respecting the grid proportions set in the container.</p>
<p>These are the properties we’ll use for that:</p>
<ul>
<li><code>grid-column-start</code></li>
<li><code>grid-column-end</code></li>
<li><code>grid-row-start</code></li>
<li><code>grid-row-end</code></li>
</ul>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">300px</span> <span class="hljs-number">300px</span>;
}

<span class="hljs-selector-class">.item1</span> {
  <span class="hljs-attribute">grid-column-start</span>: <span class="hljs-number">2</span>;
  <span class="hljs-attribute">grid-column-end</span>: <span class="hljs-number">4</span>;
}

<span class="hljs-selector-class">.item6</span> {
  <span class="hljs-attribute">grid-column-start</span>: <span class="hljs-number">3</span>;
  <span class="hljs-attribute">grid-column-end</span>: <span class="hljs-number">5</span>;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JrzZm5o6SkpvGiKZo6v8XmRDAfpajBt6mym4" alt="Image" width="730" height="636" loading="lazy"></p>
<p>The numbers correspond to the vertical line that separates each column, starting from 1:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JdCCwzrGzvd1O68dBAqIHSWh4hMbM6ttuJ8Z" alt="Image" width="745" height="691" loading="lazy"></p>
<p>The same principle applies to <code>grid-row-start</code> and <code>grid-row-end</code>, except this time instead of taking more columns, a cell takes more rows.</p>
<h4 id="heading-shorthand-syntax">Shorthand syntax</h4>
<p>Those properties have a shorthand syntax provided by:</p>
<ul>
<li><code>grid-column</code></li>
<li><code>grid-row</code></li>
</ul>
<p>The usage is simple, here’s how to replicate the above layout:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">300px</span> <span class="hljs-number">300px</span>;
}

<span class="hljs-selector-class">.item1</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / <span class="hljs-number">4</span>;
}

<span class="hljs-selector-class">.item6</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">3</span> / <span class="hljs-number">5</span>;
}
</code></pre>
<p>Another approach is to set the starting column/row, and set how many it should occupy using <code>span</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">300px</span> <span class="hljs-number">300px</span>;
}

<span class="hljs-selector-class">.item1</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / span <span class="hljs-number">2</span>;
}

<span class="hljs-selector-class">.item6</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">3</span> / span <span class="hljs-number">2</span>;
}
</code></pre>
<h3 id="heading-more-grid-configuration">More grid configuration</h3>
<h4 id="heading-using-fractions">Using fractions</h4>
<p>Specifying the exact width of each column or row is not ideal in every case.</p>
<p>A fraction is a unit of space.</p>
<p>The following example divides a grid into 3 columns with the same width, 1/3 of the available space each.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr;
}
</code></pre>
<h4 id="heading-using-percentages-and-rem">Using percentages and rem</h4>
<p>You can also use percentages, and mix and match fractions, pixels, rem and percentages:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">3rem</span> <span class="hljs-number">15%</span> <span class="hljs-number">1</span>fr <span class="hljs-number">2</span>fr
}
</code></pre>
<h4 id="heading-using-repeat">Using <code>repeat()</code></h4>
<p><code>repeat()</code> is a special function that takes a number that indicates the number of times a row/column will be repeated, and the length of each one.</p>
<p>If every column has the same width, you can specify the layout using this syntax:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">4</span>, <span class="hljs-number">100px</span>);
}
</code></pre>
<p>This creates 4 columns with the same width.</p>
<p>Or using fractions:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">4</span>, <span class="hljs-number">1</span>fr);
}
</code></pre>
<h4 id="heading-specify-a-minimum-width-for-a-row">Specify a minimum width for a row</h4>
<p>Common use case: Have a sidebar that never collapses more than a certain amount of pixels when you resize the window.</p>
<p>Here’s an example where the sidebar takes 1/4 of the screen and never takes less than 200px:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">minmax</span>(<span class="hljs-number">200px</span>, <span class="hljs-number">3</span>fr) <span class="hljs-number">9</span>fr;
}
</code></pre>
<p>You can also set just a maximum value using the <code>auto</code> keyword:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">minmax</span>(auto, <span class="hljs-number">50%</span>) <span class="hljs-number">9</span>fr;
}
</code></pre>
<p>or just a minimum value:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">minmax</span>(<span class="hljs-number">100px</span>, auto) <span class="hljs-number">9</span>fr;
}
</code></pre>
<h4 id="heading-positioning-elements-using-grid-template-areas">Positioning elements using <code>grid-template-areas</code></h4>
<p>By default elements are positioned in the grid using their order in the HTML structure.</p>
<p>Using <code>grid-template-areas</code> you can define template areas to move them around in the grid, and also to span an item on multiple rows / columns instead of using <code>grid-column</code>.</p>
<p>Here’s an example:</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">container</span>"&gt;
  &lt;<span class="hljs-selector-tag">main</span>&gt;
    ...
  &lt;/<span class="hljs-selector-tag">main</span>&gt;
  &lt;<span class="hljs-selector-tag">aside</span>&gt;
    ...
  &lt;/<span class="hljs-selector-tag">aside</span>&gt;
  &lt;<span class="hljs-selector-tag">header</span>&gt;
    ...
  &lt;/<span class="hljs-selector-tag">header</span>&gt;
  &lt;<span class="hljs-selector-tag">footer</span>&gt;
    ...
  &lt;/<span class="hljs-selector-tag">footer</span>&gt;
&lt;/<span class="hljs-selector-tag">div</span>&gt;

<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">300px</span> <span class="hljs-number">300px</span>;
  <span class="hljs-attribute">grid-template-areas</span>:
    <span class="hljs-string">"header header header header"</span>
    <span class="hljs-string">"sidebar main main main"</span>
    <span class="hljs-string">"footer footer footer footer"</span>;
}
<span class="hljs-selector-tag">main</span> {
  <span class="hljs-attribute">grid-area</span>: main;
}
<span class="hljs-selector-tag">aside</span> {
  <span class="hljs-attribute">grid-area</span>: sidebar;
}
<span class="hljs-selector-tag">header</span> {
  <span class="hljs-attribute">grid-area</span>: header;
}
<span class="hljs-selector-tag">footer</span> {
  <span class="hljs-attribute">grid-area</span>: footer;
}
</code></pre>
<p>Despite their original order, items are placed where <code>grid-template-areas</code> define, depending on the <code>grid-area</code> property associated to them.</p>
<h4 id="heading-adding-empty-cells-in-template-areas">Adding empty cells in template areas</h4>
<p>You can set an empty cell using the dot <code>.</code> instead of an area name in <code>grid-template-areas</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span> <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">300px</span> <span class="hljs-number">300px</span>;
  <span class="hljs-attribute">grid-template-areas</span>:
    <span class="hljs-string">". header header ."</span>
    <span class="hljs-string">"sidebar . main main"</span>
    <span class="hljs-string">". footer footer ."</span>;
}
</code></pre>
<h4 id="heading-fill-a-page-with-a-grid">Fill a page with a grid</h4>
<p>You can make a grid extend to fill the page using <code>fr</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr;
  <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr;
}
</code></pre>
<h4 id="heading-an-example-header-sidebar-content-and-footer">An example: header, sidebar, content and footer</h4>
<p>Here is a simple example of using CSS Grid to create a site layout that provides a header op top, a main part with sidebar on the left and content on the right, and a footer afterwards.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/M8qvpAE1DS6BoPXyfpb2VWAEbz2C8U4W587t" alt="Image" width="768" height="318" loading="lazy"></p>
<p>Here’s the markup:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"wrapper"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>Header<span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">article</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Welcome<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hi!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">article</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">aside</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Sidebar<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">aside</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">footer</span>&gt;</span>Footer<span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>and here’s the CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">header</span> {
  <span class="hljs-attribute">grid-area</span>: header;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#fed330</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
}
<span class="hljs-selector-tag">article</span> {
  <span class="hljs-attribute">grid-area</span>: content;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#20bf6b</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
}
<span class="hljs-selector-tag">aside</span> {
  <span class="hljs-attribute">grid-area</span>: sidebar;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#45aaf2</span>;
}
<span class="hljs-selector-tag">footer</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">grid-area</span>: footer;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#fd9644</span>;
}
<span class="hljs-selector-class">.wrapper</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-gap</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">3</span>fr;
  <span class="hljs-attribute">grid-template-areas</span>:
    <span class="hljs-string">"header  header"</span>
    <span class="hljs-string">"sidebar content"</span>
    <span class="hljs-string">"footer  footer"</span>;
}
</code></pre>
<p>I added some colors to make it prettier, but basically it assigns to every different tag a <code>grid-area</code> name, which is used in the <code>grid-template-areas</code> property in <code>.wrapper</code>.</p>
<p>When the layout is smaller we can put the sidebar below the content using a media query:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">500px</span>) {
  <span class="hljs-selector-class">.wrapper</span> {
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">4</span>fr;
    <span class="hljs-attribute">grid-template-areas</span>:
      <span class="hljs-string">"header"</span>
      <span class="hljs-string">"content"</span>
      <span class="hljs-string">"sidebar"</span>
      <span class="hljs-string">"footer"</span>;
  }
}
</code></pre>
<p><a target="_blank" href="https://codepen.io/flaviocopes/pen/JZWOEK">See on CodePen</a></p>
<p>These are the basics of CSS Grid. There are many things I didn’t include in this introduction but I wanted to make it very simple, so you can start using this new layout system without making it feel overwhelming.</p>
<h3 id="heading-flexbox">FLEXBOX</h3>
<p>Flexbox, also called Flexible Box Module, is one of the two modern layouts systems, along with CSS Grid.</p>
<p>Compared to CSS Grid (which is bi-dimensional), flexbox is a <strong>one-dimensional layout model</strong>. It will control the layout based on a row or on a column, but not together at the same time.</p>
<p>The main goal of flexbox is to allow items to fill the whole space offered by their container, depending on some rules you set.</p>
<p>Unless you need to support old browsers like IE8 and IE9, Flexbox is the tool that lets you forget about using</p>
<ul>
<li>Table layouts</li>
<li>Floats</li>
<li>clearfix hacks</li>
<li><code>display: table</code> hacks</li>
</ul>
<p>Let’s dive into flexbox and become a master of it in a very short time.</p>
<h3 id="heading-browser-support-1">Browser support</h3>
<p>At the time of writing (Feb 2018), it’s supported by 97.66% of the users. All the most important browsers have implemented it for years, so even older browsers (including IE10+) are covered:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/pAsJcNUmJljKeifKY7DSA8-LQasyo2vsgOoW" alt="Image" width="683" height="549" loading="lazy"></p>
<p>While we must wait a few years for users to catch up on CSS Grid, Flexbox is an older technology and can be used right now.</p>
<h3 id="heading-enable-flexbox">Enable Flexbox</h3>
<p>A flexbox layout is applied to a container, by setting</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">display</span>: <span class="hljs-selector-tag">flex</span>;
</code></pre>
<p>or</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">display</span>: <span class="hljs-selector-tag">inline-flex</span>;
</code></pre>
<p>The content <strong>inside the container</strong> will be aligned using flexbox.</p>
<h4 id="heading-container-properties">Container properties</h4>
<p>Some flexbox properties apply to the container, which sets the general rules for its items. They are</p>
<ul>
<li><code>flex-direction</code></li>
<li><code>justify-content</code></li>
<li><code>align-items</code></li>
<li><code>flex-wrap</code></li>
<li><code>flex-flow</code></li>
</ul>
<h4 id="heading-align-rows-or-columns">Align rows or columns</h4>
<p>The first property we see, <code>**flex-direction**</code>, determines if the container should align its items as rows, or as columns:</p>
<ul>
<li><code>flex-direction: row</code> places items as a <strong>row</strong>, in the text direction (left-to-right for western countries)</li>
<li><code>flex-direction: row-reverse</code> places items just like <code>row</code> but in the opposite direction</li>
<li><code>flex-direction: column</code> places items in a <strong>column</strong>, ordering top to bottom</li>
<li><code>flex-direction: column-reverse</code> places items in a column, just like <code>column</code> but in the opposite direction</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/o26IgBk91Cjdfe8h-uAl-NAULk6k5fUjTI8o" alt="Image" width="616" height="355" loading="lazy"></p>
<h4 id="heading-vertical-and-horizontal-alignment">Vertical and horizontal alignment</h4>
<p>By default, items start from the left if <code>flex-direction</code> is row, and from the top if <code>flex-direction</code> is column.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/lgTI1ZtxbWha-5GyAWbTNrmOhe03ikkpo-Gx" alt="Image" width="625" height="794" loading="lazy"></p>
<p>You can change this behavior using <code>justify-content</code> to change the horizontal alignment, and <code>align-items</code> to change the vertical alignment.</p>
<h4 id="heading-change-the-horizontal-alignment">Change the horizontal alignment</h4>
<p><code>**justify-content**</code> has 5 possible values:</p>
<ul>
<li><code>flex-start</code>: align to the left side of the container.</li>
<li><code>flex-end</code>: align to the right side of the container.</li>
<li><code>center</code>: align at the center of the container.</li>
<li><code>space-between</code>: display with equal spacing between them.</li>
<li><code>space-around</code>: display with equal spacing around them</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/3eA5Rgtjp0xnyWoQ5v5e1aWIbgmS8YgWzgdm" alt="Image" width="800" height="932" loading="lazy"></p>
<h4 id="heading-change-the-vertical-alignment">Change the vertical alignment</h4>
<p><code>**align-items**</code> has 5 possible values:</p>
<ul>
<li><code>flex-start</code>: align to the top of the container.</li>
<li><code>flex-end</code>: align to the bottom of the container.</li>
<li><code>center</code>: align at the vertical center of the container.</li>
<li><code>baseline</code>: display at the baseline of the container.</li>
<li><code>stretch</code>: items are stretched to fit the container.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1pQRvAAzAtBRjO8UI8-zpoa8rL51uKkKklZR" alt="Image" width="606" height="1317" loading="lazy"></p>
<p>A note on <code>baseline</code>:</p>
<p><code>baseline</code> looks similar to <code>flex-start</code> in this example, due to my boxes being too simple. Check out <a target="_blank" href="https://codepen.io/flaviocopes/pen/oExoJR">this Codepen</a> to have a more useful example, which I forked from a Pen originally created by <a target="_blank" href="https://twitter.com/machal">Martin Michálek</a>. As you can see there, item dimensions are aligned.</p>
<h4 id="heading-wrap">Wrap</h4>
<p>By default, items in a flexbox container are kept on a single line, shrinking them to fit in the container.</p>
<p>To force the items to spread across multiple lines, use <code>flex-wrap: wrap</code>. This will distribute the items according to the order set in <code>flex-direction</code>. Use <code>flex-wrap: wrap-reverse</code> to reverse this order.</p>
<p>A shorthand property called <code>flex-flow</code> allows you to specify <code>flex-direction</code> and <code>flex-wrap</code> in a single line, by adding the <code>flex-direction</code> value first, followed by <code>flex-wrap</code> value, for example: <code>flex-flow: row wrap</code>.</p>
<h4 id="heading-properties-that-apply-to-each-single-item">Properties that apply to each single item</h4>
<p>Up to this point, we’ve seen the properties you can apply to the container.</p>
<p>Single items can have a certain amount of independence and flexibility, and you can alter their appearance using those properties:</p>
<ul>
<li><code>order</code></li>
<li><code>align-self</code></li>
<li><code>flex-grow</code></li>
<li><code>flex-shrink</code></li>
<li><code>flex-basis</code></li>
<li><code>flex</code></li>
</ul>
<p>Let’s see them in detail.</p>
<h4 id="heading-moving-items-before-after-another-one-using-order">Moving items before / after another one using order</h4>
<p>Items are ordered based on the order they are assigned. By default every item has order <code>0</code> and the appearance in the HTML determines the final order.</p>
<p>You can override this property using <code>order</code> on each separate item. This is a property you set on the item, not the container. You can make an item appear before all the others by setting a negative value.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/B1sZQ2N0Faporf-B6QSoT9qlksFM0ul6Ova2" alt="Image" width="607" height="273" loading="lazy"></p>
<h4 id="heading-vertical-alignment-using-align-self">Vertical alignment using align-self</h4>
<p>An item can choose to <strong>override</strong> the container <code>align-items</code> setting, using <code>**align-self**</code>, which has the same 5 possible values of <code>align-items</code>:</p>
<ul>
<li><code>flex-start</code>: align to the top of the container.</li>
<li><code>flex-end</code>: align to the bottom of the container.</li>
<li><code>center</code>: align at the vertical center of the container.</li>
<li><code>baseline</code>: display at the baseline of the container.</li>
<li><code>stretch</code>: items are stretched to fit the container.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Vgk2OOS4KMX-ABecwTGMZGxu5HNOUsSCguNv" alt="Image" width="612" height="372" loading="lazy"></p>
<h4 id="heading-grow-or-shrink-an-item-if-necessary">Grow or shrink an item if necessary</h4>
<p><strong>flex-grow</strong></p>
<p>The default for any item is 0.</p>
<p>If all items are defined as 1 and one is defined as 2, the bigger element will take the space of two “1” items.</p>
<p><strong>flex-shrink</strong></p>
<p>The defaut for any item is 1.</p>
<p>If all items are defined as 1 and one is defined as 3, the bigger element will shrink 3x the other ones. When less space is available, it will take 3x less space.</p>
<p><strong>flex-basis</strong></p>
<p>If set to <code>auto</code>, it sizes an item according to its width or height, and adds extra space based on the <code>flex-grow</code> property.</p>
<p>If set to 0, it does not add any extra space for the item when calculating the layout.</p>
<p>If you specify a pixel number value, it will use that as the length value (width or height depends on if it’s a row or a column item)</p>
<p><strong>flex</strong></p>
<p>This property combines the above 3 properties:</p>
<ul>
<li><code>flex-grow</code></li>
<li><code>flex-shrink</code></li>
<li><code>flex-basis</code></li>
</ul>
<p>and provides a shorthand syntax: <code>flex: 0 1 auto</code></p>
<h3 id="heading-tables">TABLES</h3>
<p>Tables in the past were greatly overused in CSS, as they were one of the only ways we could create a fancy page layout.</p>
<p>Today with Grid and Flexbox we can move tables back to the job they were intended to do: styling tables.</p>
<p>Let’s start from the HTML. This is a basic table:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">table</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>Age<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"row"</span>&gt;</span>Flavio<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>36<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"row"</span>&gt;</span>Roger<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span>
</code></pre>
<p>By default it’s not very attractive. The browser provides some standard styles, and that’s it:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/cSv50H4eDfA17z4XhwXhlwgDCzfrtAkth840" alt="Image" width="346" height="252" loading="lazy"></p>
<p>We can use CSS to style all the elements of the table, of course.</p>
<p>Let’s start with the border. A nice border can go a long way.</p>
<p>We can apply it on the <code>table</code> element, and on the inner elements too, like <code>th</code> and <code>td</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">table</span>, <span class="hljs-selector-tag">th</span>, <span class="hljs-selector-tag">td</span> {
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#333</span>;
}
</code></pre>
<p>If we pair it with some margin, we get a nice result:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/77EZWjHTyPL1-2BHjB6PtNKGxoefvaH8Ou0N" alt="Image" width="402" height="519" loading="lazy"></p>
<p>One common thing with tables is the ability to add a color to one row, and a different color to another row. This is possible using the <code>:nth-child(odd)</code> or <code>:nth-child(even)</code> selector:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">tbody</span> <span class="hljs-selector-tag">tr</span><span class="hljs-selector-pseudo">:nth-child(odd)</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#af47ff</span>;
}
</code></pre>
<p>This gives us:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/bgYEzQ0jzePRY8Z1QsjS8Wr33gzw8Hm2R0-o" alt="Image" width="387" height="509" loading="lazy"></p>
<p>If you add <code>border-collapse: collapse;</code> to the table element, all borders are collapsed into one:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/YBEKBLgWtAy6VbpdnQCbpIzfWJYKvGPesyGA" alt="Image" width="564" height="636" loading="lazy"></p>
<h3 id="heading-centering">CENTERING</h3>
<p>Centering things in CSS is a task that is very different if you need to center horizontally or vertically.</p>
<p>In this post I explain the most common scenarios and how to solve them. If a new solution is provided by <a target="_blank" href="https://flaviocopes.com/flexbox/">Flexbox</a> I ignore the old techniques because we need to move forward, and Flexbox has been supported by browsers for years, IE10 included.</p>
<h3 id="heading-center-horizontally">Center horizontally</h3>
<h4 id="heading-text">Text</h4>
<p>Text is very simple to center horizontally using the <code>text-align</code> property set to <code>center</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-align</span>: center;
}
</code></pre>
<h4 id="heading-blocks">Blocks</h4>
<p>The modern way to center anything that is not text is to use Flexbox:</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#mysection</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: center;
}
</code></pre>
<p>any element inside <code>#mysection</code> will be horizontally centered.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/poUby5NpYUt0D8ADmTgP6wWXhjj2PMjWuK4p" alt="Image" width="618" height="218" loading="lazy"></p>
<p>Here is the alternative approach if you don’t want to use Flexbox.</p>
<p>Anything that is not text can be centered by applying an automatic margin to left and right, and setting the width of the element:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">section</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">50%</span>;
}
</code></pre>
<p>the above <code>margin: 0 auto;</code> is a shorthand for:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">section</span> {
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">margin-left</span>: auto;
  <span class="hljs-attribute">margin-right</span>: auto;
}
</code></pre>
<p>Remember to set the item to <code>display: block</code> if it's an inline element.</p>
<h3 id="heading-center-vertically">Center vertically</h3>
<p>Traditionally this has always been a difficult task. Flexbox now provides us a great way to do this in the simplest possible way:</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#mysection</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
}
</code></pre>
<p>any element inside <code>#mysection</code> will be vertically centered.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/XOIWKiWU2zPe3VNje1LpiaHur6lJu4db8Cyp" alt="Image" width="613" height="299" loading="lazy"></p>
<h3 id="heading-center-both-vertically-and-horizontally">Center both vertically and horizontally</h3>
<p>Flexbox techniques to center vertically and horizontally can be combined to completely center an element in the page.</p>
<pre><code class="lang-css"><span class="hljs-selector-id">#mysection</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/OtQEQ-F5AsSU0b49Oo5cGwoyLafxN05qmoLQ" alt="Image" width="615" height="298" loading="lazy"></p>
<p>The same can be done using <a target="_blank" href="https://flaviocopes.com/css-grid/">CSS Grid</a>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">place-items</span>: center;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
}
</code></pre>
<h3 id="heading-lists">LISTS</h3>
<p>Lists are a very important part of many web pages.</p>
<p>CSS can style them using several properties.</p>
<p><code>list-style-type</code> is used to set a predefined marker to be used by the list:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">list-style-type</span>: square;
}
</code></pre>
<p>We have lots of possible values, which you can see here <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type">https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type</a> with examples of their appearance. Some of the most popular ones are <code>disc</code>, <code>circle</code>, <code>square</code> and <code>none</code>.</p>
<p><code>list-style-image</code> is used to use a custom marker when a predefined marker is not appropriate:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">list-style-image</span>: <span class="hljs-built_in">url</span>(list-image.png);
}
</code></pre>
<p><code>list-style-position</code> lets you add the marker <code>outside</code> (the default) or <code>inside</code> of the list content, in the flow of the page rather than outside of it</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">list-style-position</span>: inside;
}
</code></pre>
<p>The <code>list-style</code> shorthand property lets us specify all those properties in the same line:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">list-style</span>: <span class="hljs-built_in">url</span>(list-image.png) inside;
}
</code></pre>
<h3 id="heading-media-queries-and-responsive-design">MEDIA QUERIES AND RESPONSIVE DESIGN</h3>
<p>In this section we’re going to first introduce media types and media feature descriptors, then we’ll explain media queries.</p>
<h4 id="heading-media-types">Media types</h4>
<p>Used in media queries and @import declarations, media types allow us to determine on which media a CSS file, or a piece of CSS, is loaded.</p>
<p>We have the following <strong>media types</strong></p>
<ul>
<li><code>all</code> means all the media</li>
<li><code>print</code> used when printing</li>
<li><code>screen</code> used when the page is presented on a screen</li>
<li><code>speech</code> used for screen readers</li>
</ul>
<p><code>screen</code> is the default.</p>
<p>In the past we had more of them, but most are deprecated as they proved to be ineffective ways of determining device needs.</p>
<p>We can use them in @import statements like this:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(myfile.css) screen;
<span class="hljs-keyword">@import</span> url(myfile-print.css) print;
</code></pre>
<p>We can load a CSS file on multiple media types separating each with a comma:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(myfile.css) screen, print;
</code></pre>
<p>The same works for the <code>link</code> tag in HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"myfile.css"</span> <span class="hljs-attr">media</span>=<span class="hljs-string">"screen"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"another.css"</span> <span class="hljs-attr">media</span>=<span class="hljs-string">"screen, print"</span> /&gt;</span>
</code></pre>
<p>We’re not limited to just using media types in the <code>media</code> attribute and in the <code>@import</code> declaration. There's more.</p>
<h4 id="heading-media-feature-descriptors">Media feature descriptors</h4>
<p>First, let’s introduce <strong>media feature descriptors</strong>. They are additional keywords that we can add to the <code>media</code> attribute of <code>link</code> or the the <code>@import</code> declaration, to express more conditionals over the loading of the CSS.</p>
<p>Here’s the list of them:</p>
<ul>
<li><code>width</code></li>
<li><code>height</code></li>
<li><code>device-width</code></li>
<li><code>device-height</code></li>
<li><code>aspect-ratio</code></li>
<li><code>device-aspect-ratio</code></li>
<li><code>color</code></li>
<li><code>color-index</code></li>
<li><code>monochrome</code></li>
<li><code>resolution</code></li>
<li><code>orientation</code></li>
<li><code>scan</code></li>
<li><code>grid</code></li>
</ul>
<p>Each of them has a corresponding min- <em>and max-</em>, for example:</p>
<ul>
<li><code>min-width</code>, <code>max-width</code></li>
<li><code>min-device-width</code>, <code>max-device-width</code></li>
</ul>
<p>and so on.</p>
<p>Some of those accept a length value which can be expressed in <code>px</code> or <code>rem</code> or any length value. It's the case of <code>width</code>, <code>height</code>, <code>device-width</code>, <code>device-height</code>.</p>
<p>For example:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(myfile.css) screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">800px</span>);
</code></pre>
<p>Notice that we wrap each block using media feature descriptors in parentheses.</p>
<p>Some accept a fixed value. <code>orientation</code>, used to detect the device orientation, accepts <code>portrait</code> or <code>landscape</code>.</p>
<p>Example:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"myfile.css"</span> <span class="hljs-attr">media</span>=<span class="hljs-string">"screen and (orientation: portrait)"</span> /&gt;</span>
</code></pre>
<p><code>scan</code>, used to determine the type of screen, accepts <code>progressive</code> (for modern displays) or <code>interlace</code> (for older CRT devices).</p>
<p>Some others want an integer.</p>
<p>Like <code>color</code> which inspects the number of bits per color component used by the device. Very low-level, but you just need to know it's there for your usage (like <code>grid</code>, <code>color-index</code>, <code>monochrome</code>).</p>
<p><code>aspect-ratio</code> and <code>device-aspect-ratio</code> accept a ratio value representing the width to height viewport ratio, which is expressed as a fraction.</p>
<p>Example:</p>
<pre><code>@<span class="hljs-keyword">import</span> url(myfile.css) screen and (aspect-ratio: <span class="hljs-number">4</span>/<span class="hljs-number">3</span>);
</code></pre><p><code>resolution</code> represents the pixel density of the device, expressed in a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/resolution">resolution data type</a> like <code>dpi</code>.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(myfile.css) screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-resolution:</span> <span class="hljs-number">100dpi</span>);
</code></pre>
<h4 id="heading-logic-operators">Logic operators</h4>
<p>We can combine rules using <code>and</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"myfile.css"</span> <span class="hljs-attr">media</span>=<span class="hljs-string">"screen and (max-width: 800px)"</span> /&gt;</span>
</code></pre>
<p>We can perform an “or” type of logic operation using commas, which combines multiple media queries:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(myfile.css) screen, print;
</code></pre>
<p>We can use <code>not</code> to negate a media query:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(myfile.css) <span class="hljs-keyword">not</span> screen;
</code></pre>
<blockquote>
<p><em>Important: <code>not</code> can only be used to negate an entire media query, so it must be placed at the beginning of it (or after a comma).</em></p>
</blockquote>
<h4 id="heading-media-queries">Media queries</h4>
<p>All those above rules we saw applied to @import or the the <code>link</code> HTML tag can be applied inside the CSS, too.</p>
<p>You need to wrap them in a <code>@media () {}</code> structure.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">800px</span>) {
  <span class="hljs-comment">/* enter some CSS */</span>
}
</code></pre>
<p>and this is the foundation for <strong>responsive design</strong>.</p>
<p>Media queries can be quite complex. This example applies the CSS only if it’s a screen device, the width is between 600 and 800 pixels, and the orientation is landscape:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">800px</span>) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">600px</span>) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">orientation:</span> landscape) {
  <span class="hljs-comment">/* enter some CSS */</span>
}
</code></pre>
<h3 id="heading-feature-queries">FEATURE QUERIES</h3>
<p>Feature queries are a recent and relatively unknown ability of CSS, but a <a target="_blank" href="https://caniuse.com/#feat=css-featurequeries">well supported</a> one.</p>
<p>We can use it to check if a feature is supported by the browser using the <code>@supports</code> keyword.</p>
<p>I think this is especially useful, at the time of writing, for checking if a browser supports CSS grid, for example, which can be done using:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> grid) {
  <span class="hljs-comment">/* apply this CSS */</span>
}
</code></pre>
<p>We check if the browser supports the <code>grid</code> value for the <code>display</code> property.</p>
<p>We can use <code>@supports</code> for any CSS property, to check any value.</p>
<p>We can also use the logical operators <code>and</code>, <code>or</code> and <code>not</code> to build complex feature queries:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> grid) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">display:</span> flex) {
  <span class="hljs-comment">/* apply this CSS */</span>
}
</code></pre>
<h3 id="heading-filters">FILTERS</h3>
<p>Filters allow us to perform operations on elements.</p>
<p>Things you normally do with Photoshop or other photo editing software, like changing the opacity or the brightness, and more.</p>
<p>You use the <code>filter</code> property. Here's an example of it applied on an image, but this property can be used on <em>any</em> element:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: &lt;something&gt;;
}
</code></pre>
<p>You can use various values here:</p>
<ul>
<li><code>blur()</code></li>
<li><code>brightness()</code></li>
<li><code>contrast()</code></li>
<li><code>drop-shadow()</code></li>
<li><code>grayscale()</code></li>
<li><code>hue-rotate()</code></li>
<li><code>invert()</code></li>
<li><code>opacity()</code></li>
<li><code>sepia()</code></li>
<li><code>saturate()</code></li>
<li><code>url()</code></li>
</ul>
<p>Notice the parentheses after each option, because they all require a parameter.</p>
<p>For example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">opacity</span>(<span class="hljs-number">0.5</span>);
}
</code></pre>
<p>means the image will be 50% transparent, because <code>opacity()</code> takes one value from 0 to 1, or a percentage.</p>
<p>You can also apply multiple filters at once:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">opacity</span>(<span class="hljs-number">0.5</span>) <span class="hljs-built_in">blur</span>(<span class="hljs-number">2px</span>);
}
</code></pre>
<p>Let’s now talk about each filter in detail.</p>
<h4 id="heading-blur"><code>blur()</code></h4>
<p>Blurs an element content. You pass it a value, expressed in <code>px</code> or <code>em</code> or <code>rem</code> that will be used to determine the blur radius.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">blur</span>(<span class="hljs-number">4px</span>);
}
</code></pre>
<h4 id="heading-opacity"><code>opacity()</code></h4>
<p><code>opacity()</code> takes one value from 0 to 1, or a percentage, and determines the image transparency based on it.</p>
<p><code>0</code>, or <code>0%</code>, means totally transparent. <code>1</code>, or <code>100%</code>, or higher, means totally visible.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">opacity</span>(<span class="hljs-number">0.5</span>);
}
</code></pre>
<p>CSS also has an <code>opacity</code> property. <code>filter</code> however can be hardware accelerated, depending on the implementation, so this should be the preferred method.</p>
<h4 id="heading-drop-shadow"><code>drop-shadow()</code></h4>
<p><code>drop-shadow()</code> shows a shadow behind the element, which follows the alpha channel. This means that if you have a transparent image, you get a shadow applied to the image shape, not the image box. If the image does not have an alpha channel, the shadow will be applied to the entire image box.</p>
<p>It accepts a minimum of 2 parameters, up to 5:</p>
<ul>
<li><em>offset-x</em> sets the horizontal offset. Can be negative.</li>
<li><em>offset-y</em> sets the vertical offset. Can be negative.</li>
<li><em>blur-radius</em>, optional, sets the blur radius for the shadow. It defaults to 0, no blur.</li>
<li><em>spread-radius</em>, optional, sets the spread radius. Expressed in <code>px</code>, <code>rem</code> or <code>em</code></li>
<li><em>color</em>, optional, sets the color of the shadow.</li>
</ul>
<p>You can set the color without setting the spread radius or blur radius. CSS understands the value is a color and not a length value.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">drop-shadow</span>(<span class="hljs-number">10px</span> <span class="hljs-number">10px</span> <span class="hljs-number">5px</span> orange);
}

<span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">drop-shadow</span>(<span class="hljs-number">10px</span> <span class="hljs-number">10px</span> orange);
}

<span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">drop-shadow</span>(<span class="hljs-number">10px</span> <span class="hljs-number">10px</span> <span class="hljs-number">5px</span> <span class="hljs-number">5px</span> #<span class="hljs-number">333</span>);
}
</code></pre>
<h4 id="heading-grayscale"><code>grayscale()</code></h4>
<p>Makes the element have a gray color.</p>
<p>You pass one value from 0 to 1, or from 0% to 100%, where 1 and 100% mean completely gray, and 0 or 0% mean the image is not touched, and the original colors remain.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">grayscale</span>(<span class="hljs-number">50%</span>);
}
</code></pre>
<h4 id="heading-sepia"><code>sepia()</code></h4>
<p>Makes the element have a sepia color.</p>
<p>You pass one value from 0 to 1, or from 0% to 100%, where 1 and 100% mean completely sepia, and 0 or 0% mean the image is not touched, and the original colors remain.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">sepia</span>(<span class="hljs-number">50%</span>);
}
</code></pre>
<h4 id="heading-invert"><code>invert()</code></h4>
<p>Invert the colors of an element. Inverting a color means looking up the opposite of a color in the HSL color wheel. Just search “color wheel” in Google if you have no idea what that means. For example, the opposite of yellow is blue, the opposite of red is cyan. Every single color has an opposite.</p>
<p>You pass a number, from 0 to 1 or from 0% to 100%, that determines the amount of inversion. 1 or 100% means full inversion, 0 or 0% means no inversion.</p>
<p>0.5 or 50% will always render a 50% gray color, because you always end up in the middle of the wheel.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">invert</span>(<span class="hljs-number">50%</span>);
}
</code></pre>
<h4 id="heading-hue-rotate"><code>hue-rotate()</code></h4>
<p>The HSL color wheel is represented in degrees. Using <code>hue-rotate()</code> you can rotate the color using a positive or negative rotation.</p>
<p>The function accepts a <code>deg</code> value.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">hue-rotate</span>(<span class="hljs-number">90deg</span>);
}
</code></pre>
<h4 id="heading-brightness"><code>brightness()</code></h4>
<p>Alters the brightness of an element.</p>
<p>0 or 0% gives a total black element. 1 or 100% gives an unchanged image.</p>
<p>Values higher than 1 or 100% make the image brighter up to reaching a total white element.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">brightness</span>(<span class="hljs-number">50%</span>);
}
</code></pre>
<h3 id="heading-contrast"><code>contrast()</code></h3>
<p>Alters the contrast of an element.</p>
<p>0 or 0% gives a total gray element. 1 or 100% gives an unchanged image.</p>
<p>Values higher than 1 or 100% give more contrast.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">contrast</span>(<span class="hljs-number">150%</span>);
}
</code></pre>
<h4 id="heading-saturate"><code>saturate()</code></h4>
<p>Alters the saturation of an element.</p>
<p>0 or 0% gives a total grayscale element (with less saturation). 1 or 100% gives an unchanged image.</p>
<p>Values higher than 1 or 100% give more saturation.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">saturate</span>();
}
</code></pre>
<h4 id="heading-url-1"><code>url()</code></h4>
<p>This filter allows to apply a filter defined in an SVG file. You point to the SVG file location.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">url</span>(filter.svg);
}
</code></pre>
<p>SVG filters are out of the scope of this piece, but you can read more on this Smashing Magazine post: <a target="_blank" href="https://www.smashingmagazine.com/2015/05/why-the-svg-filter-is-awesome/">https://www.smashingmagazine.com/2015/05/why-the-svg-filter-is-awesome/</a></p>
<h3 id="heading-transforms">TRANSFORMS</h3>
<p>Transforms allow you to translate, rotate, scale, and skew elements, in the 2D or 3D space. They are a very cool CSS feature, especially when combined with animations.</p>
<h4 id="heading-2d-transforms">2D transforms</h4>
<p>The <code>transform</code> property accepts those functions:</p>
<ul>
<li><code>translate()</code> to move elements around</li>
<li><code>rotate()</code> to rotate elements</li>
<li><code>scale()</code> to scale elements in size</li>
<li><code>skew()</code> to twist or slant an element</li>
<li><code>matrix()</code> a way to perform any of the above operations using a matrix of 6 elements, a less user friendly syntax but less verbose</li>
</ul>
<p>We also have axis-specific functions:</p>
<ul>
<li><code>translateX()</code> to move elements around on the X axis</li>
<li><code>translateY()</code> to move elements around on the Y axis</li>
<li><code>scaleX()</code> to scale elements in size on the X axis</li>
<li><code>scaleY()</code> to scale elements in size on the Y axis</li>
<li><code>skewX()</code> to twist or slant an element on the X axis</li>
<li><code>skewY()</code> to twist or slant an element on the Y axis</li>
</ul>
<p>Here is an example of a transform which changes the <code>.box</code> element width by 2 (duplicating it) and the height by 0.5 (reducing it to half):</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.box</span> {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">2</span>, <span class="hljs-number">0.5</span>);
}
</code></pre>
<p><code>[transform-origin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin)</code> lets us set the origin (the <code>(0, 0)</code> coordinates) for the transformation, letting us change the rotation center.</p>
<h4 id="heading-combining-multiple-transforms">Combining multiple transforms</h4>
<p>You can combine multiple transforms by separating each function with a space.</p>
<p>For example:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">transform</span>: <span class="hljs-selector-tag">rotateY</span>(20<span class="hljs-selector-tag">deg</span>) <span class="hljs-selector-tag">scaleX</span>(3) <span class="hljs-selector-tag">translateY</span>(100<span class="hljs-selector-tag">px</span>);
</code></pre>
<h4 id="heading-3d-transforms">3D transforms</h4>
<p>We can go one step further and move our elements in a 3D space instead of in a 2D space. With 3D, we are adding another axis, Z, which adds depth to our visuals.</p>
<p>Using the <code>perspective</code> property you can specify how far the 3D object is from the viewer.</p>
<p>Example:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.3Delement</span> {
  <span class="hljs-attribute">perspective</span>: <span class="hljs-number">100px</span>;
}
</code></pre>
<p><code>perspective-origin</code> determines the appearance of the position of the viewer, how are we looking at it in the X and Y axis.</p>
<p>Now we can use additional functions that control the Z axis, and that add up to the other X and Y axis transforms:</p>
<ul>
<li><code>translateZ()</code></li>
<li><code>rotateZ()</code></li>
<li><code>scaleZ()</code></li>
</ul>
<p>and the corresponding shorthands <code>translate3d()</code>, <code>rotate3d()</code> and <code>scale3d()</code> as shorthands for using the <code>translateX()</code>, <code>translateY()</code> and <code>translateZ()</code> functions and so on.</p>
<p>3D transforms are a bit too advanced for this handbook, but are a great topic to explore on your own.</p>
<h3 id="heading-transitions">TRANSITIONS</h3>
<p>CSS Transitions are the simplest way to create an animation in CSS.</p>
<p>In a transition, you change the value of a property, and you tell CSS to slowly change it according to some parameters, towards a final state.</p>
<p>CSS Transitions are defined by these properties:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-84q2WYZR7Ojj24SC1gD4k8ZIRNGq2pXDfSo" alt="Image" width="654" height="330" loading="lazy"></p>
<p>The <code>transition</code> property is a handy shorthand:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">transition</span>: property
              duration
              timing-function
              delay;
}
</code></pre>
<h4 id="heading-example-of-a-css-transition">Example of a CSS Transition</h4>
<p>This code implements a CSS Transition:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.one</span>,
<span class="hljs-selector-class">.three</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">142</span>, <span class="hljs-number">92</span>, <span class="hljs-number">205</span>, .<span class="hljs-number">75</span>);
  <span class="hljs-attribute">transition</span>: background <span class="hljs-number">1s</span> ease-in;
}

<span class="hljs-selector-class">.two</span>,
<span class="hljs-selector-class">.four</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">236</span>, <span class="hljs-number">252</span>, <span class="hljs-number">100</span>, .<span class="hljs-number">75</span>);
}

<span class="hljs-selector-class">.circle</span><span class="hljs-selector-pseudo">:hover</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">142</span>, <span class="hljs-number">92</span>, <span class="hljs-number">205</span>, .<span class="hljs-number">25</span>); <span class="hljs-comment">/* lighter */</span>
}
</code></pre>
<p>See the example on Glitch <a target="_blank" href="https://flavio-css-transitions-example.glitch.me/">https://flavio-css-transitions-example.glitch.me</a></p>
<p>When hovering the <code>.one</code> and <code>.three</code> elements, the purple circles, there is a transition animation that eases the change of background, while the yellow circles do not, because they do not have the <code>transition</code> property defined.</p>
<h4 id="heading-transition-timing-function-values">Transition timing function values</h4>
<p><code>transition-timing-function</code> allows you to specify the acceleration curve of the transition.</p>
<p>There are some simple values you can use:</p>
<ul>
<li><code>linear</code></li>
<li><code>ease</code></li>
<li><code>ease-in</code></li>
<li><code>ease-out</code></li>
<li><code>ease-in-out</code></li>
</ul>
<p><a target="_blank" href="https://flavio-css-transitions-easings.glitch.me/">This Glitch</a> shows how these work in practice.</p>
<p>You can create a completely custom timing function using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/single-transition-timing-function">cubic bezier curves</a>. This is rather advanced, but basically any of those functions above are built using bezier curves. We have handy names as they are common ones.</p>
<h4 id="heading-css-transitions-in-browser-devtools">CSS Transitions in Browser DevTools</h4>
<p>The Browser DevTools offer a great way to visualize transitions.</p>
<p>This is Chrome:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/l6svCI9t6bLTsuniRuxjgwOnD9i1YSseno-f" alt="Image" width="560" height="623" loading="lazy"></p>
<p>This is Firefox:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JYAWK9J6xuzeP2WVytUt8k64RUUCHl3UJmXC" alt="Image" width="713" height="537" loading="lazy"></p>
<p>From those panels you can live edit the transition and experiment in the page directly without reloading your code.</p>
<h4 id="heading-which-properties-you-can-animate-using-css-transitions">Which Properties you can Animate using CSS Transitions</h4>
<p>A lot! They are the same you can animate using CSS Animations, too.</p>
<p>Here’s the full list:</p>
<ul>
<li><code>background</code></li>
<li><code>background-color</code></li>
<li><code>background-position</code></li>
<li><code>background-size</code></li>
<li><code>border</code></li>
<li><code>border-color</code></li>
<li><code>border-width</code></li>
<li><code>border-bottom</code></li>
<li><code>border-bottom-color</code></li>
<li><code>border-bottom-left-radius</code></li>
<li><code>border-bottom-right-radius</code></li>
<li><code>border-bottom-width</code></li>
<li><code>border-left</code></li>
<li><code>border-left-color</code></li>
<li><code>border-left-width</code></li>
<li><code>border-radius</code></li>
<li><code>border-right</code></li>
<li><code>border-right-color</code></li>
<li><code>border-right-width</code></li>
<li><code>border-spacing</code></li>
<li><code>border-top</code></li>
<li><code>border-top-color</code></li>
<li><code>border-top-left-radius</code></li>
<li><code>border-top-right-radius</code></li>
<li><code>border-top-width</code></li>
<li><code>bottom</code></li>
<li><code>box-shadow</code></li>
<li><code>caret-color</code></li>
<li><code>clip</code></li>
<li><code>color</code></li>
<li><code>column-count</code></li>
<li><code>column-gap</code></li>
<li><code>column-rule</code></li>
<li><code>column-rule-color</code></li>
<li><code>column-rule-width</code></li>
<li><code>column-width</code></li>
<li><code>columns</code></li>
<li><code>content</code></li>
<li><code>filter</code></li>
<li><code>flex</code></li>
<li><code>flex-basis</code></li>
<li><code>flex-grow</code></li>
<li><code>flex-shrink</code></li>
<li><code>font</code></li>
<li><code>font-size</code></li>
<li><code>font-size-adjust</code></li>
<li><code>font-stretch</code></li>
<li><code>font-weight</code></li>
<li><code>grid-area</code></li>
<li><code>grid-auto-columns</code></li>
<li><code>grid-auto-flow</code></li>
<li><code>grid-auto-rows</code></li>
<li><code>grid-column-end</code></li>
<li><code>grid-column-gap</code></li>
<li><code>grid-column-start</code></li>
<li><code>grid-column</code></li>
<li><code>grid-gap</code></li>
<li><code>grid-row-end</code></li>
<li><code>grid-row-gap</code></li>
<li><code>grid-row-start</code></li>
<li><code>grid-row</code></li>
<li><code>grid-template-areas</code></li>
<li><code>grid-template-columns</code></li>
<li><code>grid-template-rows</code></li>
<li><code>grid-template</code></li>
<li><code>grid</code></li>
<li><code>height</code></li>
<li><code>left</code></li>
<li><code>letter-spacing</code></li>
<li><code>line-height</code></li>
<li><code>margin</code></li>
<li><code>margin-bottom</code></li>
<li><code>margin-left</code></li>
<li><code>margin-right</code></li>
<li><code>margin-top</code></li>
<li><code>max-height</code></li>
<li><code>max-width</code></li>
<li><code>min-height</code></li>
<li><code>min-width</code></li>
<li><code>opacity</code></li>
<li><code>order</code></li>
<li><code>outline</code></li>
<li><code>outline-color</code></li>
<li><code>outline-offset</code></li>
<li><code>outline-width</code></li>
<li><code>padding</code></li>
<li><code>padding-bottom</code></li>
<li><code>padding-left</code></li>
<li><code>padding-right</code></li>
<li><code>padding-top</code></li>
<li><code>perspective</code></li>
<li><code>perspective-origin</code></li>
<li><code>quotes</code></li>
<li><code>right</code></li>
<li><code>tab-size</code></li>
<li><code>text-decoration</code></li>
<li><code>text-decoration-color</code></li>
<li><code>text-indent</code></li>
<li><code>text-shadow</code></li>
<li><code>top</code></li>
<li><code>transform.</code></li>
<li><code>vertical-align</code></li>
<li><code>visibility</code></li>
<li><code>width</code></li>
<li><code>word-spacing</code></li>
<li><code>z-index</code></li>
</ul>
<h3 id="heading-animations">ANIMATIONS</h3>
<p>CSS Animations are a great way to create visual animations, not limited to a single movement like CSS Transitions, but much more articulated.</p>
<p>An animation is applied to an element using the <code>animation</code> property.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">animation</span>: spin <span class="hljs-number">10s</span> linear infinite;
}
</code></pre>
<p><code>spin</code> is the name of the animation, which we need to define separately. We also tell CSS to make the animation last 10 seconds, perform it in a linear way (no acceleration or any difference in its speed) and to repeat it infinitely.</p>
<p>You must <strong>define how your animation works</strong> using <strong>keyframes</strong>. Example of an animation that rotates an item:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@keyframes</span> spin {
  0% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">0</span>);
  }
  100% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">360deg</span>);
  }
}
</code></pre>
<p>Inside the <code>@keyframes</code> definition you can have as many intermediate waypoints as you want.</p>
<p>In this case we instruct CSS to make the transform property to rotate the Z axis from 0 to 360 grades, completing the full loop.</p>
<p>You can use any CSS transform here.</p>
<p>Notice how this does not dictate anything about the temporal interval the animation should take. This is defined when you use it via <code>animation</code>.</p>
<h4 id="heading-a-css-animations-example">A CSS Animations Example</h4>
<p>I want to draw four circles, all with a starting point in common, all 90 degrees distant from each other.</p>
<pre><code class="lang-css">&lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">container</span>"&gt;
  &lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">circle</span> <span class="hljs-selector-tag">one</span>"&gt;&lt;/<span class="hljs-selector-tag">div</span>&gt;
  &lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">circle</span> <span class="hljs-selector-tag">two</span>"&gt;&lt;/<span class="hljs-selector-tag">div</span>&gt;
  &lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">circle</span> <span class="hljs-selector-tag">three</span>"&gt;&lt;/<span class="hljs-selector-tag">div</span>&gt;
  &lt;<span class="hljs-selector-tag">div</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">circle</span> <span class="hljs-selector-tag">four</span>"&gt;&lt;/<span class="hljs-selector-tag">div</span>&gt;
&lt;/<span class="hljs-selector-tag">div</span>&gt;

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">place-items</span>: center;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
}

<span class="hljs-selector-class">.circle</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> - <span class="hljs-number">6.25em</span>);
  <span class="hljs-attribute">top</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> - <span class="hljs-number">12.5em</span>);
  <span class="hljs-attribute">transform-origin</span>: <span class="hljs-number">50%</span> <span class="hljs-number">12.5em</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">12.5em</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">12.5em</span>;
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">1em</span> <span class="hljs-number">2em</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, .<span class="hljs-number">5</span>);
}

<span class="hljs-selector-class">.one</span>,
<span class="hljs-selector-class">.three</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">142</span>, <span class="hljs-number">92</span>, <span class="hljs-number">205</span>, .<span class="hljs-number">75</span>);
}

<span class="hljs-selector-class">.two</span>,
<span class="hljs-selector-class">.four</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">236</span>, <span class="hljs-number">252</span>, <span class="hljs-number">100</span>, .<span class="hljs-number">75</span>);
}

<span class="hljs-selector-class">.one</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">0</span>);
}

<span class="hljs-selector-class">.two</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">90deg</span>);
}

<span class="hljs-selector-class">.three</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">180deg</span>);
}

<span class="hljs-selector-class">.four</span> {
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(-<span class="hljs-number">90deg</span>);
}
</code></pre>
<p>You can see them in this Glitch: <a target="_blank" href="https://flavio-css-circles.glitch.me/">https://flavio-css-circles.glitch.me</a></p>
<p>Let’s make this structure (all the circles together) rotate. To do this, we apply an animation on the container, and we define that animation as a 360 degree rotation:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@keyframes</span> spin {
  0% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">0</span>);
  }
  100% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">360deg</span>);
  }
}

<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">animation</span>: spin <span class="hljs-number">10s</span> linear infinite;
}
</code></pre>
<p>See it on <a target="_blank" href="https://flavio-css-animations-tutorial.glitch.me/">https://flavio-css-animations-tutorial.glitch.me</a></p>
<p>You can add more keyframes to have funnier animations:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@keyframes</span> spin {
  0% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">0</span>);
  }
  25% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">30deg</span>);
  }
  50% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">270deg</span>);
  }
  75% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">180deg</span>);
  }
  100% {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotateZ</span>(<span class="hljs-number">360deg</span>);
  }
}
</code></pre>
<p>See the example on <a target="_blank" href="https://flavio-css-animations-four-steps.glitch.me/">https://flavio-css-animations-four-steps.glitch.me</a></p>
<h4 id="heading-the-css-animation-properties">The CSS animation properties</h4>
<p>CSS animations offers a lot of different parameters you can tweak:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/AurqyVJOCys9sUi4S6DtBlaxKGi6evJQhsbB" alt="Image" width="747" height="699" loading="lazy"></p>
<p>The <code>animation</code> property is a shorthand for all these properties, in this order:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">animation</span>: name
             duration
             timing-function
             delay
             iteration-count
             direction
             fill-mode
             play-state;
}
</code></pre>
<p>This is the example we used above:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">animation</span>: spin <span class="hljs-number">10s</span> linear infinite;
}
</code></pre>
<h4 id="heading-javascript-events-for-css-animations">JavaScript events for CSS Animations</h4>
<p>Using JavaScript you can listen for the following events:</p>
<ul>
<li><code>animationstart</code></li>
<li><code>animationend</code></li>
<li><code>animationiteration</code></li>
</ul>
<p>Be careful with <code>animationstart</code>, because if the animation starts on page load, your JavaScript code is always executed after the CSS has been processed, so the animation is already started and you cannot intercept the event.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> container = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.container'</span>)

container.addEventListener(<span class="hljs-string">'animationstart'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  <span class="hljs-comment">//do something</span>
}, <span class="hljs-literal">false</span>)

container.addEventListener(<span class="hljs-string">'animationend'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  <span class="hljs-comment">//do something</span>
}, <span class="hljs-literal">false</span>)

container.addEventListener(<span class="hljs-string">'animationiteration'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  <span class="hljs-comment">//do something</span>
}, <span class="hljs-literal">false</span>)
</code></pre>
<h4 id="heading-which-properties-you-can-animate-using-css-animations">Which Properties You Can Animate using CSS Animations</h4>
<p>A lot! They are the same you can animate using CSS Transitions, too.</p>
<p>Here’s the full list:</p>
<ul>
<li><code>background</code></li>
<li><code>background-color</code></li>
<li><code>background-position</code></li>
<li><code>background-size</code></li>
<li><code>border</code></li>
<li><code>border-color</code></li>
<li><code>border-width</code></li>
<li><code>border-bottom</code></li>
<li><code>border-bottom-color</code></li>
<li><code>border-bottom-left-radius</code></li>
<li><code>border-bottom-right-radius</code></li>
<li><code>border-bottom-width</code></li>
<li><code>border-left</code></li>
<li><code>border-left-color</code></li>
<li><code>border-left-width</code></li>
<li><code>border-radius</code></li>
<li><code>border-right</code></li>
<li><code>border-right-color</code></li>
<li><code>border-right-width</code></li>
<li><code>border-spacing</code></li>
<li><code>border-top</code></li>
<li><code>border-top-color</code></li>
<li><code>border-top-left-radius</code></li>
<li><code>border-top-right-radius</code></li>
<li><code>border-top-width</code></li>
<li><code>bottom</code></li>
<li><code>box-shadow</code></li>
<li><code>caret-color</code></li>
<li><code>clip</code></li>
<li><code>color</code></li>
<li><code>column-count</code></li>
<li><code>column-gap</code></li>
<li><code>column-rule</code></li>
<li><code>column-rule-color</code></li>
<li><code>column-rule-width</code></li>
<li><code>column-width</code></li>
<li><code>columns</code></li>
<li><code>content</code></li>
<li><code>filter</code></li>
<li><code>flex</code></li>
<li><code>flex-basis</code></li>
<li><code>flex-grow</code></li>
<li><code>flex-shrink</code></li>
<li><code>font</code></li>
<li><code>font-size</code></li>
<li><code>font-size-adjust</code></li>
<li><code>font-stretch</code></li>
<li><code>font-weight</code></li>
<li><code>grid-area</code></li>
<li><code>grid-auto-columns</code></li>
<li><code>grid-auto-flow</code></li>
<li><code>grid-auto-rows</code></li>
<li><code>grid-column-end</code></li>
<li><code>grid-column-gap</code></li>
<li><code>grid-column-start</code></li>
<li><code>grid-column</code></li>
<li><code>grid-gap</code></li>
<li><code>grid-row-end</code></li>
<li><code>grid-row-gap</code></li>
<li><code>grid-row-start</code></li>
<li><code>grid-row</code></li>
<li><code>grid-template-areas</code></li>
<li><code>grid-template-columns</code></li>
<li><code>grid-template-rows</code></li>
<li><code>grid-template</code></li>
<li><code>grid</code></li>
<li><code>height</code></li>
<li><code>left</code></li>
<li><code>letter-spacing</code></li>
<li><code>line-height</code></li>
<li><code>margin</code></li>
<li><code>margin-bottom</code></li>
<li><code>margin-left</code></li>
<li><code>margin-right</code></li>
<li><code>margin-top</code></li>
<li><code>max-height</code></li>
<li><code>max-width</code></li>
<li><code>min-height</code></li>
<li><code>min-width</code></li>
<li><code>opacity</code></li>
<li><code>order</code></li>
<li><code>outline</code></li>
<li><code>outline-color</code></li>
<li><code>outline-offset</code></li>
<li><code>outline-width</code></li>
<li><code>padding</code></li>
<li><code>padding-bottom</code></li>
<li><code>padding-left</code></li>
<li><code>padding-right</code></li>
<li><code>padding-top</code></li>
<li><code>perspective</code></li>
<li><code>perspective-origin</code></li>
<li><code>quotes</code></li>
<li><code>right</code></li>
<li><code>tab-size</code></li>
<li><code>text-decoration</code></li>
<li><code>text-decoration-color</code></li>
<li><code>text-indent</code></li>
<li><code>text-shadow</code></li>
<li><code>top</code></li>
<li><code>transform.</code></li>
<li><code>vertical-align</code></li>
<li><code>visibility</code></li>
<li><code>width</code></li>
<li><code>word-spacing</code></li>
<li><code>z-index</code></li>
</ul>
<h3 id="heading-normalizing-css">NORMALIZING CSS</h3>
<p>The default browser stylesheet is the set of rules that browsers have to apply to give some minimum style to elements.</p>
<p>Most of the time those styles are very useful.</p>
<p>Since every browser has its own set, it’s common to find a common ground.</p>
<p>Rather than removing all defaults, like one of the <strong>CSS reset</strong> approaches does, the normalizing process removes browser inconsistencies, while keeping a basic set of rules you can rely on.</p>
<p>Normalize.css <a target="_blank" href="http://necolas.github.io/normalize.css">http://necolas.github.io/normalize.css</a> is the most commonly used solution for this problem.</p>
<p>You must load the normalizing CSS file before any other CSS.</p>
<h3 id="heading-error-handling">ERROR HANDLING</h3>
<p>CSS is resilient. When it finds an error, it does not act like JavaScript which packs up all its things and goes away altogether, terminating all the script executions after the error is found.</p>
<p>CSS tries very hard to do what you want.</p>
<p>If a line has an error, it skips it and jumps to the next line without any error.</p>
<p>If you forget the semicolon on one line:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>
  color: black;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid black;
}
</code></pre>
<p>the line with the error AND the next one will <strong>not</strong> be applied, but the third rule will be successfully applied on the page. Basically, it scans all until it finds a semicolon, but when it reaches it, the rule is now <code>font-size: 20px color: black;</code>, which is invalid, so it skips it.</p>
<p>Sometimes it’s tricky to realize there is an error somewhere, and where that error is, because the browser won’t tell us.</p>
<p>This is why tools like <a target="_blank" href="http://csslint.net/">CSS Lint</a> exist.</p>
<h3 id="heading-vendor-prefixes">VENDOR PREFIXES</h3>
<p>Vendor prefixes are one way browsers use to give CSS developers access to newer features not yet considered stable.</p>
<p>Before going on, keep in mind that this approach is declining in popularity. People now favour using <strong>experimental flags</strong>, which must be enabled explicitly in the user’s browser.</p>
<p>Why? Because developers, instead of considering vendor prefixes as a way to preview features, sometimes ship them in production — something considered harmful by the CSS Working Group.</p>
<p>Mostly because once you add a flag and developers start using it in production, browsers are in a bad position if they realise something must change. With flags, you can’t ship a feature unless you can push all your visitors to enable that flag in their browser (just joking, don’t try).</p>
<p>That said, let’s see what vendor prefixes are.</p>
<p>I specifically remember them for working with CSS Transitions in the past. Instead of just using the <code>transition</code> property, you had to do this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.myClass</span> {
    <span class="hljs-attribute">-webkit-transition</span>: all <span class="hljs-number">1s</span> linear;
    <span class="hljs-attribute">-moz-transition</span>: all <span class="hljs-number">1s</span> linear;
    <span class="hljs-attribute">-ms-transition</span>: all <span class="hljs-number">1s</span> linear;
    <span class="hljs-attribute">-o-transition</span>: all <span class="hljs-number">1s</span> linear;
    <span class="hljs-attribute">transition</span>: all <span class="hljs-number">1s</span> linear;
}
</code></pre>
<p>Now you just use</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.myClass</span> {
    <span class="hljs-attribute">transition</span>: all <span class="hljs-number">1s</span> linear;
}
</code></pre>
<p>since the property is now well supported by all modern browsers.</p>
<p>The prefixes used are:</p>
<ul>
<li><code>-webkit-</code> (Chrome, Safari, iOS Safari / iOS WebView, Android)</li>
<li><code>-moz-</code> (Safari)</li>
<li><code>-ms-</code> (Edge, Internet Explorer)</li>
<li><code>-o-</code> (Opera, Opera Mini)</li>
</ul>
<p>Since Opera is Chromium-based and Edge will soon be too, <code>-o-</code> and <code>-ms-</code> will probably soon go out of fashion. But as we said, vendor prefixes as a whole are going out of fashion, too.</p>
<p>Writing prefixes is hard, mostly because of uncertainty. Do you actually need a prefix for one property? Several online resources are outdated, too, which makes it even harder to do right. Projects like <a target="_blank" href="https://github.com/postcss/autoprefixer">Autoprefixer</a> can automate the process in its entirety without us needing to find out if a prefix is needed any more, or the feature is now stable and the prefix should be dropped. It uses data from caniuse.com, a very good reference site for all things related to browser support.</p>
<p>If you use React or Vue, projects like <code>create-react-app</code> and Vue CLI, two common ways to start building an application, use <code>autoprefixer</code> out of the box, so you don't even have to worry about it.</p>
<h3 id="heading-css-for-print">CSS FOR PRINT</h3>
<p>Even though we increasingly stare at our screens, printing is still a thing.</p>
<p>Even with blog posts. I remember one time back in 2009 I met a person that told me he made his personal assistant print every blog post I published (yes, I stared blankly for a little bit). Definitely unexpected.</p>
<p>My main use case for looking into printing usually is printing to a PDF. I might create something inside the browser, and I want to make it available as PDF.</p>
<p>Browsers make this very easy, with Chrome defaulting to “Save” when trying to print a document and a printer is not available, and Safari has a dedicated button in the menu bar:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/bgA5gq1sJ4vzRx7inVg4skJLVgDggyhDjhmF" alt="Image" width="602" height="374" loading="lazy"></p>
<h4 id="heading-print-css">Print CSS</h4>
<p>Some common things you might want to do when printing is to hide some parts of the document, maybe the footer, something in the header, the sidebar.</p>
<p>Maybe you want to use a different font for printing, which is totally legit.</p>
<p>If you have a large CSS for print, you’d better use a separate file for it. Browsers will only download it when printing:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>
      <span class="hljs-attr">src</span>=<span class="hljs-string">"print.css"</span>
      <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>
      <span class="hljs-attr">media</span>=<span class="hljs-string">"print"</span> /&gt;</span>
</code></pre>
<h4 id="heading-css-media-print">CSS @media print</h4>
<p>An alternative to the previous approach is media queries. Anything you add inside this block:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> print {
  <span class="hljs-comment">/* ... */</span>
}
</code></pre>
<p>is going to be applied only to printed documents.</p>
<h4 id="heading-links">Links</h4>
<p>HTML is great because of links. It’s called HyperText for a good reason. When printing we might lose a lot of information, depending on the content.</p>
<p>CSS offers a great way to solve this problem by editing the content, appending the link after the <code>&lt;</code>;a&gt; tag text, using:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> print {
    <span class="hljs-selector-tag">a</span><span class="hljs-selector-attr">[href*=<span class="hljs-string">'//'</span>]</span><span class="hljs-selector-pseudo">:after</span> {
        <span class="hljs-attribute">content</span>:<span class="hljs-string">" ("</span> <span class="hljs-built_in">attr</span>(href) <span class="hljs-string">") "</span>;
        <span class="hljs-attribute">color</span>: $primary;
    }
}
</code></pre>
<p>I target <code>a[href*='//']</code> to only do this for external links. I might have internal links for navigation and internal indexing purposes, which would be useless in most of my use cases. If you also want internal links to be printed, just do:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> print {
    <span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:after</span> {
        <span class="hljs-attribute">content</span>:<span class="hljs-string">" ("</span> <span class="hljs-built_in">attr</span>(href) <span class="hljs-string">") "</span>;
        <span class="hljs-attribute">color</span>: $primary;
    }
}
</code></pre>
<h4 id="heading-page-margins">Page margins</h4>
<p>You can add margins to every single page. <code>cm</code> or <code>in</code> is a good unit for paper printing.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@page</span> {
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">2cm</span>;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">2cm</span>;
    <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">2cm</span>;
    <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">2cm</span>;
}
</code></pre>
<p><code>@page</code> can also be used to only target the first page, using <code>@page :first</code>, or only the left and right pages using <code>@page :left</code> and <code>@page: right</code>.</p>
<h4 id="heading-page-breaks">Page breaks</h4>
<p>You might want to add a page break after some elements, or before them. Use <code>page-break-after</code> and <code>page-break-before</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.book-date</span> {
    <span class="hljs-attribute">page-break-after</span>: always;
}

<span class="hljs-selector-class">.post-content</span> {
    <span class="hljs-attribute">page-break-before</span>: always;
}
</code></pre>
<p>Those properties <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-after">accept a wide variety of values</a>.</p>
<h4 id="heading-avoid-breaking-images-in-the-middle">Avoid breaking images in the middle</h4>
<p>I experienced this with Firefox: images by default are cut in the middle, and continue on the next page. It might also happen to text.</p>
<p>Use</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">page-break-inside</span>: avoid;
}
</code></pre>
<p>and wrap your images in a <code>p</code> tag. Targeting <code>img</code> directly didn't work in my tests.</p>
<p>This applies to other content as well, not just images. If you notice something is cut when you don’t want, use this property.</p>
<h4 id="heading-debug-the-printing-presentation">Debug the printing presentation</h4>
<p>The Chrome DevTools offer ways to emulate the print layout:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-uiIs0O58DxJGuPKuMjjzg356Nq2On7GH7QI" alt="Image" width="631" height="461" loading="lazy"></p>
<p>Once the panel opens, change the rendering emulation to <code>print</code>:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/XO5KBdEIBUtWLlIXwISJMN3GaehM9Gfd22K7" alt="Image" width="544" height="356" loading="lazy"></p>
<h3 id="heading-wrapping-up">WRAPPING UP</h3>
<p>I hope this article helped you get up to speed with CSS and get an overview of the main features you can use to style your pages and apps. I wrote it to help you get comfortable with CSS and get you quickly up to speed with using this awesome tool that lets you create stunning designs on the Web, and I hope I achieved with this goal.</p>
<p><strong><a target="_blank" href="https://flaviocopes.com/page/css-handbook/">Click here to get a PDF / ePub / Mobi version of this post to read offline</a></strong></p>
<p>Flavio</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The pros and cons of Big Design Up Front — and what I do instead ]]>
                </title>
                <description>
                    <![CDATA[ By Benek Lisefski Can a waterfall sprint? Can a greyhound slow down? _Photo by [Unsplash](https://unsplash.com/photos/qWwpHwip31M?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText" rel="noopener" target="_blank" title="">Alvaro Reye... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-pros-and-cons-of-big-design-up-front-and-what-i-do-instead-375f00542dec/</link>
                <guid isPermaLink="false">66c362240cede4e9b1329cec</guid>
                
                    <category>
                        <![CDATA[ agile ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 17 Apr 2019 15:46:00 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*1-vRJqwOWcQq7gQIeoMmyg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Benek Lisefski</p>
<h4 id="heading-can-a-waterfall-sprint-can-a-greyhound-slow-down">Can a waterfall sprint? Can a greyhound slow down?</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/NAzp6xo8ZcYIf33ahWMwydgLqeZdntcMAiEk" alt="Image" width="800" height="533" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/photos/qWwpHwip31M?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="_blank" title=""&gt;Alvaro Reyes on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" rel="noopener" target="<em>blank" title=")</em></p>
<p>I’ve run my own independent design business for 18 years. Starting back when waterfall was all we had, then transitioning to extreme agile, and all the variations in between.</p>
<p>As a freelancer, I work for a variety of clients — large and small — on a broad range of digital products: from simple brochure websites to complex web and mobile apps. I still use a BDUF waterfall process when it suits the project. Other times the atmosphere demands a highly iterative and agile approach.</p>
<p>I often switch between these polar-opposite design methodologies on a daily basis, as I shift focus from one project to another. It’s helped me adapt to both, and realise the strengths and weaknesses of each process. Practising both methodologies regularly makes me uniquely positioned to understand when one works better than the other. And it’s got me thinking about whether BDUF still has a place in the modern design and development world.</p>
<p>Before we discuss BDUF vs. Agile, let’s start with a few definitions:</p>
<h4 id="heading-waterfall">Waterfall</h4>
<p><em>A relatively linear sequential design approach where progress flows in largely one direction (“downwards” like a waterfall) through the phases of research, conception, design, construction, testing, deployment and maintenance.</em></p>
<h4 id="heading-zooming-in-or-out">Zooming in or out</h4>
<p><em>In design, zooming out means focusing on the wholeness of a design system, evaluating its effectiveness, and ensuring it works together consistently and harmoniously.</em></p>
<p><em>Zooming in is the act of focusing on a smaller piece of the whole — a feature, page, user flow, etc.— hands-on design work that crafts individual design solutions.</em></p>
<h4 id="heading-iteration">Iteration</h4>
<p><em>A cyclic process of prototyping, testing, analysing, and refining a product or process. Based on the results of stakeholder feedback or testing, changes and refinements are made.</em></p>
<h4 id="heading-integration">Integration</h4>
<p><em>An act of combining into an integral whole.</em></p>
<h4 id="heading-cost-cheap-expensive">Cost, cheap, expensive</h4>
<p><em>In this context, it refers to the time and effort spent on design or development, not necessarily a direct relation to monetary cost.</em></p>
<h4 id="heading-engineering-development-coding">Engineering, development, coding</h4>
<p><em>Used somewhat interchangeably — to draw the line between where design stops and technical implementation begins.</em></p>
<h3 id="heading-what-is-bduf">What is BDUF?</h3>
<p>Big Design Up Front is an approach where a website, app, or software design is completed and perfected up-front, before its implementation is started. It necessitates a waterfall process, and relies on <em>prediction</em>. This was the prevailing methodology for decades before the advent of Agile. Websites and software used to be very expensive to build, so it was necessary to iron out as many kinks as possible before the costly engineering happened.</p>
<p>Think of it like charting the course of a ship. If you already know the route, the weather, the currents and tides, you can plan the trip before you hit the water. Once you leave port you don’t have to waste time getting your bearings.</p>
<p>Designers who’ve been around longer than a decade — or work outside of the Silicon Valley “product” bubble — probably honed their craft using BDUF. It’s their design comfort zone.</p>
<h4 id="heading-bduf-assumptions">BDUF assumptions</h4>
<ul>
<li>We can fully know the goals, requirements, and scope of design up front — and these are unlikely to experience significant changes.</li>
<li>Design revisions are generally harder and more expensive to make after code has been written. Efficiency is gained by sorting out as much as possible in design.</li>
<li>We can and must judge if a design solution is good or effective before it’s fully functional.</li>
<li>Engineers can pinpoint development challenges while still in design, so we can find alternative design solutions before hitting code.</li>
<li>If left to their own devices, engineers will make a mess of things. Design needs to lead the way or UX and aesthetics will suffer.</li>
</ul>
<h4 id="heading-bduf-strengths">BDUF strengths</h4>
<ul>
<li>If you know exactly what you want, this is the most efficient way to get there.</li>
<li>Since all design is done at once, there’s ample opportunity for zooming out, integrating often, and designing holistically.</li>
<li>User experience is designed and refined by designers, and that design documentation dictates the functionality for engineers to develop. Each role plays to their strengths.</li>
<li>Easy to cost and schedule design, as it’s a known quantity from the start.</li>
</ul>
<h4 id="heading-bduf-weaknesses">BDUF weaknesses</h4>
<ul>
<li>Not easily adaptable to changes in scope, or pivots in purpose. You may have to swim back up the waterfall to start again if goals or requirements move.</li>
<li>Design is not as easily tested and validated, because no part of it is fully functional until near the end of the linear process.</li>
<li>Doesn’t take advantage of new learnings or better solutions that may arise during later stages of the waterfall process.</li>
</ul>
<h3 id="heading-agile-amp-emergent-design">Agile &amp; Emergent Design</h3>
<p>The agile development methodology was designed for complex, non-deterministic, non-linear projects. It prioritises being <em>adaptive</em> rather than <em>predictive</em>, reducing the leap of faith that’s needed before evidence is obtained.</p>
<p>Agile aims to break a project down into smaller chunks. Cross-functional teams then use sprints with short-time frames to work through accelerated versions of the entire waterfall process — with the goal to design, produce, and test something in each sprint. Their learnings are then integrated into the project’s evolving scope, and help shape the direction of the next sprints and iterations.</p>
<p>If BDUF is a very well-documented trip planned in advance, Agile is getting your ship out of the port with only a vague idea of where you’re going, and then exploring, planning and adapting in the water. It’s a series of small bets rather than a single well-calculated wager.</p>
<p>The <em>Manifesto for Agile Software Development</em> is based on twelve principles (via <a target="_blank" href="https://en.wikipedia.org/wiki/Agile_software_development">Wikipedia</a>):</p>
<ol>
<li>Customer satisfaction by early and continuous delivery of valuable software.</li>
<li>Welcome changing requirements, even in late development.</li>
<li>Deliver working software frequently (weeks rather than months)</li>
<li>Close, daily cooperation between business people and developers</li>
<li>Projects are built around motivated individuals, who should be trusted</li>
<li>Face-to-face conversation is the best form of communication (co-location)</li>
<li>Working software is the primary measure of progress</li>
<li>Sustainable development, able to maintain a constant pace</li>
<li>Continuous attention to technical excellence and good design</li>
<li>Simplicity — the art of maximizing the amount of work not done — is essential</li>
<li>Best architectures, requirements, and designs emerge from self-organizing teams</li>
<li>Regularly, the team reflects on how to become more effective, and adjusts accordingly</li>
</ol>
<h4 id="heading-emergent-design">Emergent Design</h4>
<p>Agile methodologies require a new way of thinking which has been described as <em>emergent design</em>. Emergent design aims to do the opposite as BDUF — minimal or no design up front so we can get to shipping, testing, and validating as quickly as possible.</p>
<h4 id="heading-emergent-design-assumptions">Emergent design assumptions</h4>
<ul>
<li>We can’t fully understand the problem or its ideal solution without a lot of testing and learning. The requirements and design must be <em>deduced</em>, so it’s better to start building the testing ASAP.</li>
<li>Change is cheaper in code than it is during design. (Or at least equally expensive).</li>
<li>Design cannot be judged or validated until it’s built and usable in the real world.</li>
<li>Designers may create technically impossible or expensive solutions if their work isn’t frequently integrated and tested.</li>
<li>Too much design up front (and <em>any</em> documentation) is wasted effort, as requirements will change or new solutions will emerge before that design is even implemented.</li>
</ul>
<h4 id="heading-emergent-design-strengths">Emergent design strengths</h4>
<ul>
<li>Design evolves over time and can take advantage of new learnings.</li>
<li>Design is a collaborative effort and not a solo, reclusive process. As <a target="_blank" href="https://medium.com/@manuel.dahm/scrum-master-designer-a-partnership-with-vast-potentials-be3fc3d1cab">Manuel Dahm said</a>: <em>“This requires the designer to move from the lonely ivory tower of creative genius into the shared apartment of the team mind.”</em></li>
<li>Design and development happen in parallel, which facilitates tremendous cross-team collaboration and rapid problem-solving. Fires can be put out at the first sign of smoke.</li>
<li>Little is left to assumption or intuition. Design is only implemented if it’s proven by data to succeed. Uncertainty about design effectiveness is removed.</li>
</ul>
<h4 id="heading-emergent-design-weaknesses">Emergent design weaknesses</h4>
<ul>
<li>Agile can be too output-focused, and encourages the feature factory.</li>
<li>Ironically, the context of sprints allows for more frequent integration on the macro level, but provides fewer opportunities for deep, holistic design thinking. Too much narrow focus and not enough wide vision means less chance for integration on the level of design systems. This can lead to a mediocre, inconsistent design which lacks polish and wholeness.</li>
<li>Design is difficult to cost because it’s a moving target dictated by stakeholder feedback and sprint cycles. Full scope of design may not emerge until halfway (or further) through a project.</li>
<li>The <em>sprint and repeat</em> cycle often concludes when “good enough” design emerges. Then it ships without much opportunity to elevate design past mediocrity. Designers lose their priorities of quality control when decision are dictated by data alone.</li>
</ul>
<h3 id="heading-just-enough-design-up-front">Just Enough Design Up Front</h3>
<blockquote>
<p>“Big design up front is dumb, but doing no design up front is even dumber.”</p>
<p>– Dave Thomas</p>
</blockquote>
<p>I used to think agile was the enemy of good design, but then I realised it’s just that <em>bad</em> agile doesn’t leave room for good design. I resisted embracing an agile way or working because many of my experiences highlighted the weaknesses of emergent design, and didn’t make up for them with their strengths.</p>
<p>In <a target="_blank" href="https://hackernoon.com/is-agile-the-enemy-of-good-design-14a35806cde7"><em>Is Agile the Enemy (of Good Design)?</em></a>, John Cutler says <strong>“Good” waterfall beats abused Agile any day.</strong></p>
<p>I would have to agree.</p>
<p>Any product development methodology is <strong>trying to answer design questions when it’s cheapest to do so</strong>. Agile supporters strongly believe it’s cheapest in small increments during short sprints. BDUF works when it’s cheapest up front and considered as a wholeness. But neither of them work <em>for designers</em> when they don’t produce a good design result.</p>
<p><strong>I don’t believe either BDUF or Agile find the right balance.</strong> It’s somewhere in between. Therefore my preferred design methodology is Just Enough Design Up Front (JEDUF).</p>
<h4 id="heading-jeduf-to-the-rescue">JEDUF to the rescue</h4>
<p>JEDUF recognises that some overarching design is required in order to enable more detailed work. We can’t always shoot from the hip with “cowboy development”. First, we need a few goalposts. We need architecture and design to create a foundation for our sprints.</p>
<ul>
<li>Early design work can be rough, but should always be as good as it can be, given the available information at the time. Yes, much more design work will have to emerge later, but we don’t want to redo any design if we can get it right the first time.</li>
<li>Up-front design should be considered the most fundamental aspects of a project or product, so it informs the priorities to build and test during early sprints. In other terms, identify the highest risks, and then design for them first. This lays the foundation for a design system, stress-tested early and often by developed pieces of highest value. Some call this necessary up-front design the “primitive whole”.</li>
</ul>
<h4 id="heading-beyond-jeduf">Beyond JEDUF</h4>
<p>My own version of JEDUF includes opportunities for design decompression and integration at various stages during the project. I call it <strong>Just Enough Design Up Front &amp; Middle</strong>.</p>
<p>JEDUF&amp;M balances small sprints — zoomed-in focus — and opportunities for holistic design integration from a wide perspective. When a critical mass of functionality has emerged, the sprint cycle can be paused for deeper design to be considered.</p>
<p>Think of it like another up-front design session, only its goals are about <em>cohesion</em> rather than <em>exploration</em>. Once the design system feels holistic and under control — integrating and harmonising the revisions from previous sprints and learnings — the next round of sprints begins. It’s up to the designer to recognise when the need for a “middle” design break is required, and not let the project get too caught up in the minutiae.</p>
<p>I’ve found JEDUF&amp;M to be the ultimate design methodology. It balances the adaptiveness, quick iterations, and focus on validation which makes agile so powerful — while also allowing for periods of rest, integration, and holistic design system thinking that can get lost among sprints and feature delivery.</p>
<p>If, even under this ideal balance of methodologies, you find yourself anxious about the number of uncertainties, think of it this way instead: <strong>embrace the uncertainty</strong>. Now <em>you’re in a position to shape what those constraints become</em>, rather than having them predetermined and dictated to you. This is more responsibility, but also more flexibility. If you handle that role with aplomb, you’ll deliver a result with no regrets or compromises, even if the process is more challenging along the way.</p>
<h3 id="heading-theres-still-plenty-of-room-for-bduf">There’s still plenty of room for BDUF</h3>
<p>You can’t afford to dismiss this dinosaur completely. Big Design Up Front is a very valid and efficient model when used on the right projects.</p>
<p><strong>The benefit of up-front design increases as the system complexity decreases.</strong></p>
<p>Not all designers are working on complex, enterprise apps, with variable stakeholder goals and uncertain solutions. Not every project requires massive exploration, testing, and customer validation.</p>
<p>I can’t imagine taking an agile approach to designing and building a simple brochure or portfolio website. My clients would think I’m mad. In these cases, BDUF is still alive and kicking.</p>
<p>BDUF and Agile are two ends of a single spectrum. Identify what you need to validate before, during, and after you build, and then tailor your process to facilitate the right design at the right time. Most projects will fall somewhere in the middle of the spectrum, not the radical fringes.</p>
<p>And let’s not forget that the waterfall process doesn’t have to be as rigid and linear as its critics make it out to be. BDUF can still “deliver early and often”, collect stakeholder feedback, iterate rapidly, and evolve over time. It’s just that this evolution happens completely in the realm of design.</p>
<p>We can make mini-waterfalls within our big waterfall. There are plenty of useful ways to achieve small validations and move forward without an entire cross-functional team pushing it straight into code and rushing to ship.</p>
<p>BDUF doesn’t mean there’s no ability to learn, adapt, and improve design through feedback and iteration. If that’s what you think BDUF is, maybe you’ve been doing it wrong all these years?</p>
<p><em>Please</em> ? <em>c<strong>lap</strong> if you found this valuable, and ?</em> f<em>o<strong>llow me f</strong>or more writing like this, as I unfold 18 years of freelance design knowledge ?</em> </p>
<h4 id="heading-subscribehttpssoloworkcosubscribe-to-get-my-best-articles-in-your-inbox"><a target="_blank" href="https://solowork.co/subscribe">Subscribe</a> to get my best articles in your inbox.</h4>
<p>This story can also be found on <a target="_blank" href="https://solowork.co/story/r-i-p-big-design-up-front">solowork.co</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ We need a new document markup language — here is why ]]>
                </title>
                <description>
                    <![CDATA[ By Christian Neumanns Introduction: What’s the Problem? There are many document markup languages available already. Wikipedia lists over 70 variations in its List of document markup languages — among them HTML, Markdown, Docbook, Asciidoctor, reStruc... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/we-need-a-new-document-markup-language-c22e0ec44e15/</link>
                <guid isPermaLink="false">66c364d68e244e1678738616</guid>
                
                    <category>
                        <![CDATA[ documentation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ markup ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                    <category>
                        <![CDATA[ writing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 16 Apr 2019 16:39:47 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*ge4Z5bQFJwk5AUA8DjHgNQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Christian Neumanns</p>
<h3 id="heading-introduction-whats-the-problem">Introduction: What’s the Problem?</h3>
<p>There are many document markup languages available already. Wikipedia lists over 70 variations in its <a target="_blank" href="https://en.wikipedia.org/wiki/List_of_document_markup_languages">List of document markup languages</a> — among them HTML, Markdown, Docbook, Asciidoctor, reStructuredText, etc.</p>
<p>Why, then, does the title of this article suggest we need <em>yet another one</em>???</p>
<p>What’s the problem?</p>
<p>There are two fundamental problems with the existing document markup languages: Either they are not easy to use, or they are not well suited to write complex documents, such as technical articles, user manuals, or books. An example of “not easy to use, but suited for complex documents” would be Docbook. An example of “easy to use, but not suited for complex documents” would be Markdown.</p>
<p>Of course, the above categorization is simplistic. But it should serve as a good starting point to get the gist of this article which aims to delineate the kind of problems that occur in practice. You’ll see many representative examples of markup code that illustrates what’s wrong, complemented by links to more information.</p>
<p>You’ll also discover a <em>new</em> markup language. Lots of examples will demonstrate how a new syntax can lead to a language that is “easy to use and suited for complex documents”. A <em>proof-of-concept</em> implementation is already available. More on this later.</p>
<h3 id="heading-preliminary-remarks">Preliminary Remarks</h3>
<p>Please note:</p>
<ul>
<li>This article is about document markup languages used to write <em>text documents</em>, such as books and articles published on the net. There are other markup languages used to describe specific data, such as mathematical formulas, images, and geographic information, but these are out of scope of this article. However, some ideas presented in this article might be applied to other kinds of markup languages as well.</li>
<li>This article focuses solely on the <em>syntax</em> of markup languages. We will not discuss other aspects that are also important in the choice of a suitable markup language, such as: support on your OS, ease of installation and dependencies, the tool chain available to create final documents, the quality of documentation, price, customer/user support, etc.</li>
<li>Readers of this article should have some basic experience with a markup language like HTML, Markdown, Asciidoctor, or similar.</li>
<li>Readers not aware of the <em>many</em> advantages of document markup languages might first want to read:<br><a target="_blank" href="https://medium.freecodecamp.org/the-advantages-of-document-markup-languages-vs-wysiwyg-editors-829dc8362219">Advantages of Document Markup Languages vs WYSIWYG Editors</a> (Word Processors)</li>
</ul>
<h3 id="heading-inconveniences-part-1">Inconveniences / Part 1</h3>
<p>Let us first consider some well-known markup languages and have a look at some inconveniences.</p>
<h4 id="heading-html">HTML</h4>
<p>HTML is the language of the web. So, why not write everything in HTML? The reasons to discard this option are well known. Let’s quickly recapitulate them.</p>
<p>HTML is cumbersome to write. Nobody wants to write XML code by hand, although editors with HTML/XML support might help.</p>
<p>Some frequent writing tasks require non-trivial HTML code.</p>
<p>Suppose we want to display a horizontally centered image with a simple black border and a link. The HTML code an inexperienced user would expect to work could look like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"ball.png"</span> <span class="hljs-attr">align</span>=<span class="hljs-string">"center"</span> <span class="hljs-attr">border</span>=<span class="hljs-string">"yes"</span> <span class="hljs-attr">link</span>=<span class="hljs-string">"http://www.example.com/ball"</span>&gt;</span>
</code></pre>
<p>But the code he or she actually has to write is cumbersome and there are different ways to do it. Here is one way:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"text-align: center"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"http://www.example.com/ball"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"ball.png"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"border:1px solid black;"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>HTML lacks “productivity features for writers”, such as:</p>
<ul>
<li>Automatic generation of a table of contents, index, glossary, etc.</li>
<li>Variables used to hold recurring values</li>
<li>Splitting a document into different files</li>
</ul>
<p>Other inconveniences will be shown later.</p>
<h4 id="heading-markdown">Markdown</h4>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Markdown">Markdown</a> is a very popular, lightweight markup language. It is easy to learn and use, and well suited for short and simple texts, such as comments in forums, readme files, etc.</p>
<p>However, it suffers from the following problems that make it unsuitable for complex or big documents (e.g. technical articles, user manuals, and books):</p>
<ul>
<li>The original Markdown defined by John Gruber lacks many features expected by writers, such as tables (only embedded HTML tables are supported), automatic generation of table of contents, syntax highlighting, file splitting, etc.</li>
<li>There is no unique, unambiguous specification for Markdown. Many flavors of Markdown exist, with different rules and different features supported. This leads to incompatibility issues when markup code is shared. <a target="_blank" href="https://commonmark.org/">CommonMark</a> is an attempt to solve this problem. However, the specification is huge and not completed yet (at the time of writing, April 2019, version 0.28, dated 2017–08–01, is the latest one).</li>
<li>Markdown has similar problems and limitations to those shown later in chapter “Inconveniences / Part 2”. These flaws can quickly become an annoyance when you use Markdown for anything else than short, simple texts.</li>
</ul>
<p>Here is a list of articles with more information about Markdown’s shortcomings:</p>
<ul>
<li><a target="_blank" href="http://www.ericholscher.com/blog/2016/mar/15/dont-use-markdown-for-technical-docs/">Why You Shouldn’t Use “Markdown” for Documentation</a></li>
<li><a target="_blank" href="https://www.red-gate.com/simple-talk/blogs/sundown-on-markdown/">Sundown on Markdown?</a></li>
<li><a target="_blank" href="http://www.wilfred.me.uk/blog/2012/07/30/why-markdown-is-not-my-favourite-language/">Why Markdown Is Not My Favourite Language</a></li>
</ul>
<h4 id="heading-docbook">Docbook</h4>
<p><a target="_blank" href="https://docbook.org/">Docbook</a> is an XML-based markup language that uses semantic tags to describe documents.</p>
<p>It has probably the most complete set of features among all markup languages. It has been used by many authors, is pre-installed on some Linux distributions, and is supported by many organizations and publishers. Docbook has been successfully used to create, publish, and print lots of big documents of all kinds.</p>
<p>But it has the following drawbacks:</p>
<p>It uses XML and a verbose syntax. Look at the following example, borrowed from <a target="_blank" href="https://en.wikipedia.org/wiki/DocBook">Wikipedia</a>:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">book</span> <span class="hljs-attr">xml:id</span>=<span class="hljs-string">"simple_book"</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://docbook.org/ns/docbook"</span> <span class="hljs-attr">version</span>=<span class="hljs-string">"5.0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Very simple book<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">chapter</span> <span class="hljs-attr">xml:id</span>=<span class="hljs-string">"chapter_1"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Chapter 1<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">para</span>&gt;</span>Hello world!<span class="hljs-tag">&lt;/<span class="hljs-name">para</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">para</span>&gt;</span>I hope that your day is proceeding <span class="hljs-tag">&lt;<span class="hljs-name">emphasis</span>&gt;</span>splendidly<span class="hljs-tag">&lt;/<span class="hljs-name">emphasis</span>&gt;</span>!<span class="hljs-tag">&lt;/<span class="hljs-name">para</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">chapter</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">chapter</span> <span class="hljs-attr">xml:id</span>=<span class="hljs-string">"chapter_2"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Chapter 2<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">para</span>&gt;</span>Hello again, world!<span class="hljs-tag">&lt;/<span class="hljs-name">para</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">chapter</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">book</span>&gt;</span>
</code></pre>
<p>Would you enjoy writing and maintaining such code?</p>
<p>Now compare the above code with the following one, written in a modern markup language like Asciidoctor:</p>
<pre><code>= Very simple book

== Chapter <span class="hljs-number">1</span>

Hello world!

I hope that your day is proceeding _splendidly_!

== Chapter <span class="hljs-number">2</span>

Hello again, world!
</code></pre><p>Docbook is also complex, and therefore hard to learn and use.</p>
<p>Output produced by Docbook, especially HTML, looks old-fashioned (see examples on its website). Of course, presentation can be customized, but this is not an easy task.</p>
<h4 id="heading-latex">LaTeX</h4>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/LaTeX">LaTeX</a> is a high-quality typesetting system. It is widely used in academia to create scientific documents. It is considered to be the best option for writing PDF documents containing lots of mathematic formulas and equations.</p>
<p>I never used LaTeX myself, because I don’t write scientific documents — just articles and books to be published on the web. Therefore, I don’t want to comment on it too much. However, it is important to mention it because of its popularity in academia.</p>
<p>LaTeX’s unique syntax seems verbose to me, and a bit complex. Here is an abbreviated example from <a target="_blank" href="https://en.wikipedia.org/wiki/LaTeX#Example">Wikipedia</a>:</p>
<pre><code class="lang-latex">\documentclass{article}
\usepackage{amsmath}
\title{\LaTeX}

\begin{document}
    \maketitle
    \LaTeX{} is a document preparation system ...

    % This is a comment
    \begin{align}
        E_0 &amp;= mc^2 \\
        E &amp;= \frac{mc^2}{\sqrt{1-\frac{v^2}{c^2}}}
    \end{align}  
\end{document}
</code></pre>
<p>The article <a target="_blank" href="https://texfaq.org/FAQ-LaTeX2HTML">Conversion from (La)TeX to HTML</a> states that converting LaTeX math to HTML is “a challenge”.</p>
<p>Some markup languages allow LaTeX snippets to be embedded in their markup code, which can be very useful if you need the power of LaTeX for maths. There are other options to display maths on the web, such as <a target="_blank" href="https://www.mathjax.org/">Mathjax</a> or <a target="_blank" href="https://en.wikipedia.org/wiki/MathML">MathML</a> (an ISO standard and part of HTML5).</p>
<h3 id="heading-popular-for-big-documents">Popular for Big Documents</h3>
<p>A impressive number of markup languages have emerged. Many of them use a syntax similar to Markup, and are therefore easy to learn and use. Some have more features than Markdown and are even extensible. However, as soon as we start writing complex documents, corner-cases and limits diminish the initial joy of using them.</p>
<p>Two popular markup languages used for big documents are Asciidoctor (an improved version of <a target="_blank" href="https://en.wikipedia.org/wiki/AsciiDoc">Asciidoc</a>), and <a target="_blank" href="https://en.wikipedia.org/wiki/ReStructuredText">reStructuredText</a> (an improved version of StructuredText). We will have a look at them soon.</p>
<h3 id="heading-practical-markup-language-pml">Practical Markup Language (PML)</h3>
<p>Before moving on to the most interesting part of this article, let me briefly introduce the new markup language I mentioned already in the introduction.</p>
<p>The language is called <strong><em>Practical</em></strong> <em>Markup Language (PML)</em>.</p>
<blockquote>
<p>“fitting the needs of a particular situation in a helpful way; helping to solve a problem or difficulty; effective or suitable”</p>
<p><em>— definition of ‘practical’ in the Cambridge Dictionary</em></p>
</blockquote>
<p>I started the <a target="_blank" href="http://www.practical-programming.org/pml/index.html">PML project</a> a few months ago because I couldn’t find a markup language that was easy to use <em>and</em> well suited for big, complex documents, such as a user manual.</p>
<p>In the next section we’ll look at examples of markup code written in PML, compared to code written in other languages. So let’s first mention two basic PML syntax rules needed to understand the upcoming examples.</p>
<p>A PML document is a tree of nodes (similar to an XML/XHTML document). Each node starts with a <code>{</code>, followed by a tag name. Each node ends with a <code>}</code>. A node can contain text or child nodes.</p>
<p>For example, here is a node containing text that will be rendered in italics:</p>
<pre><code>{i bright}
</code></pre><p>This node starts with <code>{i</code> , and ends with <code>}</code>. <code>i</code> is the tag name. In this case <code>i</code> is an abbreviation for <code>italic</code>, which means that the node's content will be rendered in <em>italics</em>. The content of this node is the text <code>bright</code>. The above PML markup code will be rendered as:<br> <em>bright</em></p>
<p>Some nodes have attributes, used to specify additional properties of the node (besides its tag name).</p>
<p>For example, the title of a chapter is defined with attribute <code>title</code>, as follows:</p>
<pre><code>{chapter title=A Nice Surprise
    Once upon a time ...
}
</code></pre><p>There is not much more to say about the basic concept of PML syntax. For more insight, and a description of features not used in this article, please consult the <a target="_blank" href="http://www.practical-programming.org/pml/docs/User_Manual/PML_User_Manual.html">PML User Manual</a>.</p>
<p>You can download and play around with a free implementation of PML. But please note: PML is a <em>work in progress</em>. There are missing features, you might encounter bugs, and backwards compatibility is currently not guaranteed.</p>
<p>I use PML myself to write all my web documents, such as this article. For links to more real-life examples please visit the <a target="_blank" href="http://www.practical-programming.org/pml/about/faq.html#examples">FAQ</a>.</p>
<h3 id="heading-inconveniences-part-2">Inconveniences / Part 2</h3>
<p>I this section we’ll look at examples that reveal <em>some</em> problems encountered with markup languages. This is by no means an exhaustive enumeration of all troubles and corner cases. The aim is to just show a few examples that demonstrate the kind of inconveniences and limits encountered in the real world.</p>
<p>For each example the markup code will be shown in <a target="_blank" href="https://www.w3.org/TR/html/">HTML</a>, <a target="_blank" href="https://asciidoctor.org/">Asciidoctor</a>, <a target="_blank" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>, and <a target="_blank" href="http://www.practical-programming.org/pml/">PML</a>.</p>
<p>If you want to try out some code, you can use the following online testers (no need to install anything on your PC):</p>
<ul>
<li><a target="_blank" href="https://www.w3schools.com/tryit/">HTML</a></li>
<li><a target="_blank" href="https://asciidoclive.com">Asciidoctor</a></li>
<li><a target="_blank" href="http://rst.ninjs.org">reStructuredText</a></li>
</ul>
<p>An online tester for PML is not yet available. You have to install PML on a Windows PC if you want to try it out.</p>
<h3 id="heading-font-styles">Font Styles</h3>
<p>Font styles (<em>italic</em>, <strong>bold</strong>, <code>monospace</code>, etc.) are often used in all kinds of documents, so good support is essential.</p>
<p>But as we will see, surprises and limits can emerge, as soon as we have to deal with non-trivial cases. Let’s look at <em>some</em> examples to illustrate this.</p>
<h3 id="heading-part-of-a-sentence-in-italics">Part of a Sentence in Italics</h3>
<p>Suppose we want to write:<br> They called it <em>Harmonic States</em>, a good name.</p>
<p>This is a trivial case, and all languages support it.</p>
<p><strong>HTML</strong>:</p>
<pre><code>They called it &lt;i&gt;Harmonic States&lt;/i&gt;, a good name.
</code></pre><p><strong>Asciidoctor</strong>:</p>
<pre><code>They called it _Harmonic States_, a good name.
</code></pre><p><strong>reStructuredText</strong>:</p>
<pre><code>They called it *Harmonic States*, a good name.
</code></pre><p><strong>PML</strong>:</p>
<pre><code>They called it {i Harmonic States}, a good name.
</code></pre><h3 id="heading-part-of-a-word-in-italics">Part of a Word in Italics</h3>
<p>We want to write:<br> She _un_wrapped the challenge first.</p>
<p><strong>HTML</strong>:</p>
<pre><code>She &lt;i&gt;un&lt;/i&gt;wrapped the challenge first.
</code></pre><p><strong>Asciidoctor</strong>:</p>
<pre><code>She __un__wrapped the challenge first.
</code></pre><p>Note that we have to use two underscores. Using a single underscore (as in the first example), would result in:<br> She _un_wrapped the challenge first.</p>
<p><strong>reStructuredText</strong>:</p>
<pre><code>She *un*\wrapped the challenge first.
</code></pre><p>Note that the letter w has to be escaped (preceded by a backslash) for reasons explained <a target="_blank" href="http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#character-level-inline-markup">here</a>. If the letter is not escaped then a warning is displayed and the result is:<br> She <em>un</em>wrapped the challenge first.</p>
<p><strong>PML</strong>:</p>
<pre><code>She {i un}wrapped the challenge first.
</code></pre><h3 id="heading-text-in-bold-and-italic">Text in Bold And Italic</h3>
<p>We want to write:<br> They were all <strong><em>totally flabbergasted</em></strong>.</p>
<p><strong>HTML</strong>:</p>
<pre><code>They were all &lt;b&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">i</span>&gt;</span>totally flabbergasted<span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span></span>&lt;/b&gt;.
</code></pre><p><strong>Asciidoctor</strong>:</p>
<pre><code>They were all *_totally flabbergasted_*.
</code></pre><p><strong>reStructuredText:</strong></p>
<p>Combining bold and italic is not supported in reStructuredText, but there are some <a target="_blank" href="https://stackoverflow.com/questions/11984652/bold-italic-in-restructuredtext">complicated workarounds</a>.</p>
<p><strong>PML:</strong></p>
<pre><code>They were all {b {i totally flabbergasted}}.
</code></pre><h3 id="heading-real-life-example">Real-Life Example</h3>
<p>Here is an example inspired by an Asciidoctor user who <a target="_blank" href="https://github.com/asciidoctor/asciidoctor/issues/2020">asked</a> how to display:<br> <strong>_id</strong> <em>optional</em>.</p>
<p>Let’s make the exercise a little bit more interesting by also displaying:<br> _<em>id</em> <strong>optional</strong>.</p>
<p><strong>HTML</strong>:</p>
<pre><code>&lt;b&gt;_id&lt;<span class="hljs-regexp">/b&gt; &lt;i&gt;optional&lt;/i</span>&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">i</span>&gt;</span>_id<span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span></span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">b</span>&gt;</span>optional<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span></span>
</code></pre><p>No surprise here. It just works as expected.</p>
<p><strong>Asciidoctor:</strong></p>
<p>Intuitive attempt:</p>
<pre><code>*_id* _optional_
__id_ *optional*
</code></pre><p>The first line doesn’t work, it produces:<br> <strong><em>id</em></strong> _<em>optional</em></p>
<p>However, the second line works, which is a bit counterintuitive.</p>
<p>If normal text includes a character that is also used for markup (in our case the <code>_</code> preceding <code>id</code>), then the character must be escaped. This is a fundamental rule in pretty much all markup languages. For example in HTML a <code>&amp;</code>lt; must be escaped wi<code>th &amp;</code>lt;. Many languages (including Asciidoctor and PML) use a backslash prefix (e.<code>g.</code> \r) to escape. So let's rewrite the code:</p>
<pre><code>*\_id* _optional_
_\_id_ *optional*
</code></pre><p>This doesn’t work in Asciidoctor. It produces<br> <strong>_id</strong> <em>optional</em><br>and<br>_id <strong>optional</strong></p>
<p>Here is a correct version, as suggested in an answer to the user’s question:</p>
<pre><code>*pass:[_]id* _optional_
<span class="hljs-attr">_pass</span>:[_]id_ *optional*
</code></pre><p>Another answer suggests this solution:</p>
<pre><code>*_id* __optional__
___id__ *optional*
</code></pre><p>More edge case are documented in chapters <a target="_blank" href="https://asciidoctor.org/docs/user-manual/#unconstrained-formatting-edge-cases">Unconstrained formatting edge cases</a> and <a target="_blank" href="https://asciidoctor.org/docs/user-manual/#escaping-unconstrained-quotes">Escaping unconstrained quotes</a> of the Asciidoctor User Manual.</p>
<p><strong>reStructuredText:</strong></p>
<pre><code>**_id** *optional*
*_id* **optional**
</code></pre><p>There is no problem here, because the character <code>_</code> is not used in reStructuredText to define markup.</p>
<p>However, suppose we wanted to write:<br> <em><em>id</em></em> <strong><em>optional</em></strong>.</p>
<p>Here is the code:</p>
<pre><code>*\*id\** ***optional***
</code></pre><p>Note that the <code>*</code>s in <code>id</code> must be escaped, but the <code>*</code>s in <code>optional</code> don't need to be escaped.</p>
<p><strong>PML:</strong></p>
<pre><code>{b _id} {i optional}
{i _id} {b optional}
</code></pre><h3 id="heading-nested-font-styles">Nested Font Styles</h3>
<p>Nested font styles of the same kind (e.g. <code>&lt;i&gt;...&lt;i&gt;..</code>....) occur rarely in text written by humans, but they could be more or less frequent in auto-generated markup code. If they are not supported then the tool that generates the markup code becomes more complicated to implement, because it must track the font styles that are active already, in order to avoid nesting them.</p>
<p>So, how is this supported in the different languages?</p>
<p><strong>HTML:</strong></p>
<pre><code>&lt;i&gt;This is &lt;i&gt;excellent&lt;<span class="hljs-regexp">/i&amp;gt;, isn't it?&lt;/i</span>&gt;
</code></pre><p>No problem, it produces<br><em>This is excellent, isn’t it?</em></p>
<p><strong>Asciidoctor:</strong></p>
<pre><code>_This is _excellent_, isn<span class="hljs-string">'t it?_</span>
</code></pre><p>The above code is obviously ambiguous: Are the italics nested or do we want to italicize “This is “ and “, isn’t it?”. When I tested it, the result was neither of it:<br>_This is <em>excellent</em>, isn’t it?_</p>
<p>As far as I now, Asciidoctor doesn’t support nested font styles of the same kind.</p>
<p><strong>reStructuredText:</strong></p>
<p>The reStructuredText specification <a target="_blank" href="http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#inline-markup">states</a>: “Inline markup cannot be nested.” However, no error is displayed if it <em>is</em> nested, and the result is unspecified.</p>
<p><strong>PML:</strong></p>
<pre><code>{i This is {i excellent}, isn<span class="hljs-string">'t it?}</span>
</code></pre><p>Font styles of the same kind can be nested in PML. The above code results in:<br><em>This is excellent, isn’t it?</em></p>
<h3 id="heading-nested-chapters">Nested Chapters</h3>
<p>Suppose we are writing an article titled “New Awesome Product” that contains four chapters. The structure looks as follows:</p>
<pre><code>New Awesome Product
    Introduction
    More features
    Faster
    Less resources
</code></pre><p>Later on we decide to insert chapter “Advantages” as a parent of the three last chapters. The structure now becomes:</p>
<pre><code>New Awesome Product
    Introduction
    Advantages
        More features
        Faster
        Less resources
</code></pre><p>What are the <em>changes</em> required in the markup code to pass from version 1 to version 2? Can we simply insert the code for a new chapter? Let’s see.</p>
<p><strong>HTML:</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/PoEYqgtazrmE2KEXHHEdSVyBd1XCISQurRxT" alt="Image" width="594" height="253" loading="lazy"></p>
<p>Note: Code <em>changes</em> are displayed in bold.</p>
<p>As shown above, besides inserting the new chapter, we have to change the markup for the three child chapters: <code>h2</code> must be changed to <code>h3</code>.</p>
<p><strong>Asciidoctor:</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/h6RYuEiJ5YHGqr6yjJ7UKEivRxOfhNKbc9Fs" alt="Image" width="474" height="388" loading="lazy"></p>
<p>Again, we have to change the markup for the three child chapters: <code>==</code> must be changed to <code>===</code></p>
<p>Note: The blank lines between the chapters are required, otherwise the document is not rendered correctly.</p>
<p><strong>reStructuredText:</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/iLno1NIDCRQW-AtE7E1R-Bp6lToSFfbQETlj" alt="Image" width="438" height="443" loading="lazy"></p>
<p>The markup for the three child chapters must be changed: All occurrences of <code>=</code> must be changed to <code>-</code></p>
<p>The non-trivial rules for reStructuredText’s sections can be looked up <a target="_blank" href="http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#sections">here</a>.</p>
<p><strong>PML:</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-z7E6Sv0f4-ZPQlj9ldRKMTiFLdzBjbjNCTF" alt="Image" width="656" height="307" loading="lazy"></p>
<p>In PML, there is no need to change the code of the three child chapters.</p>
<p><strong>Bottom Line:</strong></p>
<p>In all languages, except PML, the markup code of all child chapters must be adapted if a parent chapter is inserted.</p>
<p>This is not a deal-breaker in case of small articles with few chapters. But image you are writing your next big article or book with lots of chapters and frequent changes. Now, the necessity to manually update child chapters can quickly turn into a daunting, boring, and error-prone task.</p>
<p>Note: Asciidoctor provides a <code>leveloffset</code> variable that can be used to change the level of chapters. This might be useful in some cases, but it also creates additional unneeded complexity, as can be seen <a target="_blank" href="https://github.com/asciidoctor/asciidoctor/issues/530">here</a> and <a target="_blank" href="https://github.com/asciidoctor/asciidoctor/issues/1616">here</a>.</p>
<p>A more serious kind of problem can arise in the following situation: Imagine a set of different documents that share some common chapters. To avoid code duplication, the common chapters are stored in different files, and an <code>insert file</code> directive is used in the main documents. This works fine as long as the levels of all common chapters are the same in all documents. But troubles emerge if this is not the case.</p>
<p>It is also worth to mention that HTML, Asciidoctor and reStructuredText don’t protect us against wrong chapter hierarchies. For example, you don’t get a warning or error if a chapter of level 2 contains a direct child chapter of level 4.</p>
<p>In a language like PML, the above problems simply don’t exist, because the level is not specified in the markup code. All chapters (of any level) are defined with the same, unique syntax. The chapters’ tree structure (i.e. the level of each chapter) is automatically defined by the parser. And wrong hierarchies in the markup code, such as a missing <code>}</code> to close a chapter, are flagged by an error message.</p>
<h3 id="heading-lists">Lists</h3>
<p>In Asciidoctor the kind of problems we have seen with chapter hierarchies can also arise with list hierarchies (e.g. lists that contain lists). The reason is the same as for chapters: <a target="_blank" href="https://asciidoctor.org/docs/user-manual/#nested">Asciidoctor lists</a> use different markup code to explicitly specify the level of list items (<code>*</code> for level 1, <code>**</code> for level 2, etc.). Moreover, there are a number of complications you have to be aware of when working with <a target="_blank" href="https://asciidoctor.org/docs/user-manual/#complex-list-content">complex list content</a>.</p>
<p>In reStructuredText, <a target="_blank" href="https://stackoverflow.com/questions/5550089/how-to-create-a-nested-list-in-restructuredtext">nested lists</a> are created using indentation and blank lines. This works fine for simple nested lists, but creates other problems in more complex cases (not discussed here). Using whitespace (e.g. blank lines and indentation) to define structure in markup code is a bad idea, as we’ll see soon.</p>
<p>In HTML and PML, the above problems don’t exist with lists because the syntax for parent- and child nodes is the same.</p>
<h3 id="heading-whitespace-and-indentation">Whitespace And Indentation</h3>
<p>At first, using whitespace to define structure seams like a good idea. Look at the following example:</p>
<pre><code>parent
    child <span class="hljs-number">1</span>
    child <span class="hljs-number">2</span>
</code></pre><p>The structure is very easy to read <em>and</em> write. No noisy special markup characters are needed.</p>
<p>It is therefore tempting for markup language designers to use whitespace as a simple way to define structure. Unfortunately, this works well only for simple structures, and has other inconveniences we’ll see soon.</p>
<p>Therefore, a simple, but important rule must be applied in markup languages designed to work well with complex content:</p>
<blockquote>
<p>“Whitespace doesn’t change the structure or semantics of the document.”  </p>
<p><em>— whitespace-insignificant-rule</em></p>
</blockquote>
<p>What does this mean?</p>
<p>First, let us define <em>whitespace</em>: Whitespace is any set of one or more consecutive spaces, tabs, new lines, and other Unicode characters that represent space.</p>
<p>In our context, the above rule means that:</p>
<p>Within text, a set of <em>several</em> (i.e. more than one) whitespace characters is treated the same as a <em>single</em> space character.</p>
<p>For example, this code:</p>
<pre><code>a beautiful
    flower
</code></pre><p>… is identical to this one:</p>
<pre><code>a beautiful flower
</code></pre><p>Between structural elements, a set of whitespace characters is insignificant.</p>
<p>For example, this code:</p>
<pre><code>&lt;table&gt;

    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span></span>
</code></pre><p>… is identical to this one:</p>
<pre><code>&lt;table&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span></span>
</code></pre><p>A special case of whitespace is <em>indentation</em> (leading whitespace at the beginning of a line). The above rule implies that indentation is insignificant too. Indentation doesn’t change the result of the final document.</p>
<p>Applying the <em>whitespace-insignificant</em> rule is important, because it leads to significant advantages:</p>
<ul>
<li>There is no need to learn, apply and worry about complex whitespace rules (see examples below).<br>Violating the <em>whitespace-insignificant</em> rule in a markup specification adds unneeded complexity, and can lead to markup code that is ugly, error-prone, and difficult to maintain, especially in the case of nested lists.</li>
<li>Whitespace can freely be used by authors to format the markup code in a more understandable, presentable and attractive way (pretty printing). For example, lists (and lists of lists) can be indented to display their structure in a visually clear and maintainable way, without the risk of changing the underlying structure.</li>
<li>Text blocks can be copy/pasted without the need to adapt whitespace.</li>
<li>If shared text blocks (stored in different files) are imported into several documents with different structures, there is no risk of changing or breaking the structure.</li>
<li>There is no unexpected or obscure behavior if the whitespace is not visible for human readers. Some examples:  </li>
<li>a mixture of whitespace characters, such as spaces and tabs, especially when used to indent code  </li>
<li>whitespace at the end of a line  </li>
<li>whitespace in empty lines  </li>
<li>visually impaired (blind) people who can’t read whitespace<br>Note: To alleviate the pain, some editors provide a <em>display-whitespace</em> mode.</li>
<li>Tools that generate markup code, as well as markup parsers are generally easier to create.</li>
<li>In some situations it is useful to reduce whitespace to a minimum (e.g. no new lines), in order to save storage space and improve performance.</li>
</ul>
<p>If you want a few examples demonstrating the kind of technical problems that arise if whitespace is significant, you can read:</p>
<ul>
<li><a target="_blank" href="https://www.quora.com/What-are-the-downsides-to-whitespace-indentation-rather-than-requiring-curly-braces">What are the downsides to whitespace indentation rather than requiring curly braces?</a></li>
<li><a target="_blank" href="https://fsharpforfunandprofit.com/posts/fsharp-syntax/">F# syntax: indentation and verbosity</a></li>
<li><a target="_blank" href="https://github.com/nodeca/js-yaml/issues/80">Issue in nodeca/js-yaml</a></li>
</ul>
<p>So, how is whitespace handled in the languages we are discussing in this article?</p>
<p><strong>HTML:</strong></p>
<p>HTML applies the <em>whitespace-insignificant</em> rule.</p>
<p>For a thorough explanation, look at this excellent article written by Patrick Brosset: <a target="_blank" href="https://medium.com/@patrickbrosset/when-does-white-space-matter-in-html-b90e8a7cdd33">When does white space matter in HTML?</a>.</p>
<p><strong>Asciidoctor:</strong></p>
<p>In Asciidoctor, whitespace is significant in some cases.</p>
<p>This can lead to surprising behavior and problems with no easy or no satisfying solution. Some examples can be seen <a target="_blank" href="https://github.com/asciidoctor/asciidoctor/issues/686">here</a> and <a target="_blank" href="https://github.com/asciidoctor/asciidoctor/issues/623">here</a>.</p>
<p><strong>reStructuredText:</strong></p>
<p>reStructuredText has whitespace rules that are ‘a bit surprising’.</p>
<p>For example, writing <code>*very*</code> results in <em>very</em> (text in italics, as expected). However, <code>* very*</code> results in <em> very</em> (no italics!), because of the whitespace preceding "very". To understand why, the answer might be found in chapter <a target="_blank" href="http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#whitespace">Whitespace</a> of the specification.</p>
<p><strong>PML:</strong></p>
<p>Similar to HTML, PML applies the <em>whitespace-insignificant</em> rule.</p>
<p>There is one exception: For practical reasons, a blank line between two text blocks results in a paragraph break. This means that instead of writing:</p>
<pre><code>{p text <span class="hljs-keyword">of</span> paragraph <span class="hljs-number">1</span>}
{p text <span class="hljs-keyword">of</span> paragraph <span class="hljs-number">2</span>}
</code></pre><p>… we can simply write:</p>
<pre><code>text <span class="hljs-keyword">of</span> paragraph <span class="hljs-number">1</span>

text <span class="hljs-keyword">of</span> paragraph <span class="hljs-number">2</span>
</code></pre><p>Note: Sometimes, whitespace <em>is</em> significant in text. For example whitespace must be preserved in source code examples. Or, in verbatim text, several consecutive spaces or new lines must be preserved in the final document. All languages support this. However, in reStructuredText it’s not always obvious how to it, as shown <a target="_blank" href="https://stackoverflow.com/questions/51198270/how-do-i-create-a-new-line-with-restructuredtext">here</a>.</p>
<h3 id="heading-other-inconveniences">Other Inconveniences</h3>
<p>As seen already, some markup languages systematically use opening and closing tags. An example would be <code>&lt;</code>;i&gt;<code>; an</code>d  in HTML. All XML-based languages, as well as PML belong to this class of languages.</p>
<p>Without digging into details, here are some drawbacks that can occur in languages that do <em>not</em> (or not always) use pairs of distinct opening/closing tags (e.g. Markdown, Asciidoctor, and reStructuredText):</p>
<p><strong>Editor support</strong><br>Creating good, reliable editor support is more difficult to develop. Examples of useful editor features are:</p>
<ul>
<li>syntax highlighting for markup code</li>
<li>markup code completion</li>
<li>visualizing pairs of block start/end marks (e.g. <code>{</code> and its corresponding <code>}</code>)</li>
<li>block collapsing/expanding<br>In the case of languages that use distinct opening/closing tags, the two last features work out-of-the-box in some editors. For example, PML uses <code>{</code> and <code>}</code> for node boundaries. This is also used in many programming languages (C, Java, Javascript, etc.) and therefore block features implemented for programming languages will also work for PML.</li>
</ul>
<p><strong>Document validation</strong><br>Fewer syntax and structure errors can be detected automatically. This can lead to more time spent on debugging documents. Or, even worse, there might be silently ignored errors that end up in wrong output (Did I really fail to spot the missing warning block on page 267 of my 310 pages book?).</p>
<p><strong>Parsers</strong><br>It is more difficult to create parsers (i.e. programs that read markup code) that work well in all cases. If different parsers read the same markup code, there is an increased risk of getting different results for corner-cases.</p>
<p><strong>Auto-generated markup code</strong><br>Tools that generate markup code programmatically are more difficult to create. For example, if whitespace is significant, or font styles cannot be nested, then additional state must be updated and tracked, in order to respect these rules.</p>
<h3 id="heading-my-own-experience">My Own Experience</h3>
<p>When I started writing technical documents a few years ago, I used Docbook. It took me some time to learn it, but after that I never stumbled on anything I couldn’t do. Docbook is powerful. However, I disliked typing verbose XML code. I tried some XML editors, but gave up. Finally I just wrote complete text blocks unformatted in Notepad++, and then adorned the text with the necessary markup code. It was frustrating and time-consuming. Moreover, I couldn’t find a stylesheet that produced good-looking web documents, and I didn’t have the patience, motivation, and experience to fiddle around with big, complex CSS files and adapt them.</p>
<p>Later on I discovered Asciidoctor. What a relief. Everything was so much simpler and the web documents were beautiful, out of the box. Asciidoctor’s documentation is great, and I think the community is helpful and active. However, when I started to write more complex and bigger documents, I had to deal with problems similar to those described in the previous sections. At one point, I had to develop a specific pre- and post-processor to solve a problem for which I couldn’t find a solution in Asciidoctor/Gitbook.</p>
<p>An intriguing question emerged: “Why do these problems not exist in Docbook?”.</p>
<p>To make a long story short, I concluded that we need a new markup syntax. The key points to success would be:</p>
<ul>
<li>easy to learn: few, simple, consistent and predictable rules (no exceptions)</li>
<li>easy to write and read</li>
<li>well-structured documents with no ambiguities</li>
<li>powerful enough to create big, complex documents without the need for “special rules, tricks, or workarounds”</li>
</ul>
<p>After a period of investigating, pondering, programming, testing and improving, the <a target="_blank" href="http://www.practical-programming.org/pml/index.html">Practical Markup Language (PML)</a> was born. Since then, I never looked back again. Today I write all my web documents in PML (including this article).</p>
<p>Of course, when I started to create PML, it was to cover my own needs. So, I am probably biased. Hopefully this article contains enough factual examples, but I encourage you to leave a comment if you see anything wrong, unfair, or missing. I appreciate constructive feedback of any kind, and I will update the article if needed.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>As demonstrated in this article, a good number of problems encountered with existing document markup languages vanish with the PML syntax.</p>
<p>Now we should come together to improve PML and make it more powerful, so that it covers more use cases and more people can benefit from it.</p>
<p>Please help to spread the word. Or try out PML and send feedback, so that we know what needs to be refined. Your voice counts!</p>
<p>The vision is to create the best possible document markup language and all necessary tools, so that writers can focus on writing and enjoy creating beautiful documents in a minimum of time — without worrying about unneeded complexity.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A first look at firstBorn, React Native’s new component library ]]>
                </title>
                <description>
                    <![CDATA[ By Sameeha Rahman [first-born](https://github.com/99xt/first-born) is a React Native UI Component Framework, which follows the design methodology Atomic Design by Brad Frost. Version 1.0.0 was recently published as an npm module on the 1st of April (... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-first-look-at-firstborn-react-natives-new-component-library-51403077a632/</link>
                <guid isPermaLink="false">66d460c555db48792eed3f9b</guid>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React Native ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 16 Apr 2019 16:21:13 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*JtQqp-vPqOOfvcT_V6jkVQ.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sameeha Rahman</p>
<p><code>[first-born](https://github.com/99xt/first-born)</code> is a React Native UI Component Framework, which follows the design methodology <a target="_blank" href="http://atomicdesign.bradfrost.com/chapter-2/">Atomic Design by Brad Frost</a>.</p>
<p>Version 1.0.0 was recently published as an <a target="_blank" href="https://www.npmjs.com/package/@99xt/first-born">npm module</a> on the 1st of April (it ain’t no joke though…).</p>
<p>In this article, we will see a demo of the existing components offered by <code>first-born</code>.</p>
<h3 id="heading-the-design-methodology">The Design Methodology</h3>
<p>The Atomic Design methodology follows the principle that user interfaces can be deconstructed to 5 different phases.</p>
<p>According to this design methodology, the phases are described as follows:</p>
<ul>
<li>Atoms: The basic, standalone elements, like Text, Icons, Buttons or TextInput boxes.</li>
<li>Molecules: A combination of different atoms, which together have better operational value. For example, a TextInput with a Text label to explain the content or display an error in data entered.</li>
<li>Organisms: A combination of different molecules functioning together to form complex structures. For example, a form of many TextInput molecules.</li>
<li>Template: A combination of different organisms that form the basis of the page. This includes the layout and context of these organisms.</li>
<li>Page: All the above working together in a single real-life instance, gives rise to a page. It is also the actual implementation of the template.</li>
</ul>
<h3 id="heading-getting-started">Getting Started</h3>
<p>Let us first create a new React Native app using the CLI:</p>
<pre><code>react-native init firstBornExample
</code></pre><p>Once it is created, move into the app folder:</p>
<pre><code>cd firstBornExample
</code></pre><p>To add <code>first-born</code> into the app, install it like this:</p>
<pre><code>npm i --save @<span class="hljs-number">99</span>xt/first-born
</code></pre><p><code>first-born</code> has two other dependencies we will need to install ourselves.</p>
<pre><code>npm i --save create-react-<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">react</span>-<span class="hljs-title">native</span>-<span class="hljs-title">vector</span>-<span class="hljs-title">icons</span></span>
</code></pre><p>We will then need to follow <a target="_blank" href="https://github.com/oblador/react-native-vector-icons#installation">this guide</a> to set up <code>react-native-vector-icons</code> for the app.</p>
<p>create-react-class does not have additional set-up steps.</p>
<p>And we’re good to go!</p>
<h3 id="heading-usage">Usage</h3>
<p>To import the components, the statement will look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">name</span> <span class="hljs-attr">of</span> <span class="hljs-attr">component</span>&gt;</span> } from '@99xt/first-born'</span>
</code></pre>
<p>The module comes with the following inbuilt components:</p>
<h4 id="heading-atoms">Atoms</h4>
<p><a target="_blank" href="https://github.com/99xt/first-born#text"><strong>Text</strong></a></p>
<p>The <code>Text</code> atom has a fixed set of sizes. These sizes differ depending on the underlying app platform. We can also pass a color to this <code>Text</code> atom.</p>
<pre><code class="lang-js">&lt;Text size=<span class="hljs-string">"h4"</span>&gt;first-born example&lt;/Text&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*7jJPnGkJJZrFZIftUhHF7g.png" alt="Image" width="294" height="73" loading="lazy">
<em>Text (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#icon"><strong>Icon</strong></a></p>
<p>The <code>Icon</code> atom is built on top of <code>react-native-vector-icons</code> Ionicons class. Ionicons come with two different renditions of one icon for both Android and iOS. This class will render the icon according to the underlying platform.</p>
<pre><code class="lang-js">&lt;Icon name=<span class="hljs-string">"heart"</span> color=<span class="hljs-string">"red"</span>/&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*PUTR7NmtSQ56wiYJBb6D3A.png" alt="Image" width="47" height="44" loading="lazy">
<em>Icon (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#button"><strong>Button</strong></a></p>
<p>The <code>Button</code> atom can be rendered in multiple ways. It only accepts <code>Texts</code>, <code>Icons</code>, and <code>Images</code> as child items to display. It has 3 different sizes, as well as 4 different tags that will render the button in many combinations.</p>
<pre><code class="lang-js">render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"small"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Small<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Default<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"large"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Large<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"heart"</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Default<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">rounded</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"heart"</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Rounded<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">block</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"heart"</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Block<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">rounded</span> <span class="hljs-attr">block</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"heart"</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>{"Rounded &amp; Block"}<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">outline</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"heart"</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Outline<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">outline</span> <span class="hljs-attr">transparent</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"heart"</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>{"Outline &amp; Transparent"}<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
    );
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*5L8jA5r6UmDOJlXRHp_M1g.gif" alt="Image" width="461" height="631" loading="lazy">
<em>Buttons (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#input"><strong>Input</strong></a></p>
<p>The <code>Input</code> atom is a styled <code>react-native TextInput</code>. It displays a colored border to the user if the TextInput is in focus. The <code>onChangeText</code> method is mandatory.</p>
<pre><code class="lang-js">&lt;Input placeholder=<span class="hljs-string">"Name"</span> onChangeText={<span class="hljs-built_in">this</span>.handleTextChange} /&gt;
...
handleTextChange = <span class="hljs-function">(<span class="hljs-params">text</span>) =&gt;</span> {
  <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">text</span>: text })
}
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*HV4fnn4A_FnBGoYOyDMDbg.gif" alt="Image" width="461" height="83" loading="lazy">
<em>Input (Android)</em></p>
<p>This also supports indicating an error to the user. To use this feature, we will need to create a validation method. This method should return a boolean depending on the validity of the text entered. One such scenario is checking if an email address follows the conventional format. This method is that passed in the <code>isValid</code> property.</p>
<pre><code class="lang-js">checkInputValidity = <span class="hljs-function">(<span class="hljs-params">text</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> regex = <span class="hljs-regexp">/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/</span>;
  <span class="hljs-keyword">return</span> regex.test(text);
}
...
&lt;Input placeholder=<span class="hljs-string">"Email"</span> isValid={<span class="hljs-built_in">this</span>.checkInputValidity} /&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*N0hTkCyRQ3FKQdx7nDXV3A.gif" alt="Image" width="461" height="104" loading="lazy">
<em>Input Validation (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#textarea"><strong>TextArea</strong></a></p>
<p>The <code>TextArea</code> atom is a styled <code>react-native TextInput</code>. It displays a colored border to the user if the TextInput is in focus. It also increases in height with more data entered.</p>
<pre><code class="lang-js">&lt;TextArea placeholder=<span class="hljs-string">"Description"</span>/&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*M8YCAvfmqFSIDUSTbasbEA.gif" alt="Image" width="461" height="195" loading="lazy">
<em>TextArea (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#picker"><strong>Picker</strong></a></p>
<p>The <code>Picker</code> atom is a styled <code>react-native Picker</code> component. On Android, the picker is a dropdown that extends from the initial <code>Picker</code> component. On iOS, clicking the <code>first-born Picker</code> will open a modal for the user to pick the value.</p>
<pre><code class="lang-js">&lt;Picker&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Picker.Item</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"1"</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Picker.Item</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"2"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"2"</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Picker.Item</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"3"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"3"</span> /&gt;</span></span>
&lt;/Picker&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*5e5zk7wIKmZRuzw2Gvy--A.gif" alt="Image" width="461" height="251" loading="lazy">
<em>Picker (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#datepicker"><strong>DatePicker</strong></a></p>
<p>The <code>DatePicker</code> atom is a styled <code>react-native View</code> component, which looks like a <code>TextInput</code>. On Android, when the <code>View</code> is clicked, it runs the <code>[DatePickerAndroid](https://facebook.github.io/react-native/docs/datepickerandroid)</code> <a target="_blank" href="https://facebook.github.io/react-native/docs/datepickerandroid">API</a>. On iOS, clicking the <code>View</code> will open a modal for the user to pick the date from the <code>[DatePickerIOS](https://facebook.github.io/react-native/docs/datepickerios)</code> component.</p>
<pre><code class="lang-js">&lt;DatePicker /&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*NNBTVrTRxq-BnhAd5Rwfwg.gif" alt="Image" width="461" height="688" loading="lazy">
<em>DatePicker (Android)</em></p>
<h4 id="heading-molecules">Molecules</h4>
<p><a target="_blank" href="https://github.com/99xt/first-born#formdatepicker"><strong>FormDatePicker</strong></a></p>
<p>This molecule uses the <code>DatePicker</code> atom and includes the <code>Text</code> atom as a label. The label property of this element is mandatory.</p>
<pre><code class="lang-js">&lt;FormDatePicker label=<span class="hljs-string">"Date"</span> /&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*OfW_Tlb2oBPAN9dIEhnzEg.png" alt="Image" width="467" height="117" loading="lazy">
<em>FormDatePicker (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#formpicker"><strong>FormPicker</strong></a></p>
<p>This molecule uses the <code>Picker</code> atom and includes the <code>Text</code> atom as a label. The label property of this element is mandatory.</p>
<pre><code class="lang-js">&lt;FormPicker label=<span class="hljs-string">"Number"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Picker.Item</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"1"</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Picker.Item</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"2"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"2"</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Picker.Item</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"3"</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"3"</span> /&gt;</span></span>
&lt;/FormPicker&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*E0WRwIPgUlfQM2zAJRe1jQ.png" alt="Image" width="466" height="134" loading="lazy">
<em>FormPicker (Android)</em></p>
<p>We can also pass data as an array of objects, which have the keys’ <code>value</code> and <code>label</code>. The data in both keys need to be of type String.</p>
<pre><code class="lang-js">pickerData = [
    {
        <span class="hljs-attr">value</span>: <span class="hljs-string">"1"</span>,
        <span class="hljs-attr">label</span>: <span class="hljs-string">"1"</span>
    },
    {
        <span class="hljs-attr">value</span>: <span class="hljs-string">"2"</span>,
        <span class="hljs-attr">label</span>: <span class="hljs-string">"2"</span>
    },
    {
        <span class="hljs-attr">value</span>: <span class="hljs-string">"3"</span>,
        <span class="hljs-attr">label</span>: <span class="hljs-string">"3"</span>
    }
];
...
&lt;FormPicker label=<span class="hljs-string">"Number"</span> pickerData={<span class="hljs-built_in">this</span>.pickerData} /&gt;
</code></pre>
<p><a target="_blank" href="https://github.com/99xt/first-born#forminput"><strong>FormInput</strong></a></p>
<p>This molecule uses the <code>Input</code> atom and includes the <code>Text</code> atom as a label. The label property of this element is mandatory.</p>
<pre><code class="lang-js">&lt;FormInput label=<span class="hljs-string">"Name"</span> /&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*WkEj7U4QjEMVVnzgKFUpyw.png" alt="Image" width="467" height="124" loading="lazy">
<em>FormInput (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#formtextarea"><strong>FormTextArea</strong></a></p>
<p>This molecule uses the <code>TextArea</code> atom and includes the <code>Text</code> atom as a label. The label property of this element is mandatory.</p>
<pre><code class="lang-js">&lt;FormTextArea label=<span class="hljs-string">"Description"</span> /&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*FvN6n9CSgREAlyA8dB3BrQ.png" alt="Image" width="468" height="182" loading="lazy">
<em>FormTextArea (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#card"><strong>Card</strong></a></p>
<p>The <code>Card</code> molecule displays a <code>View</code> with an image, heading, and description. Of the three, the heading is mandatory. The style of this molecule differs according to the underlying platform.</p>
<pre><code class="lang-js">&lt;Card title=<span class="hljs-string">"Heading Only"</span> /&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Card</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Heading"</span> <span class="hljs-attr">description</span>=<span class="hljs-string">"And Description"</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Card</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Heading"</span> <span class="hljs-attr">description</span>=<span class="hljs-string">"Description"</span> <span class="hljs-attr">image</span>=<span class="hljs-string">{require(</span>"<span class="hljs-attr">.</span>/<span class="hljs-attr">path</span>/<span class="hljs-attr">to</span>/<span class="hljs-attr">an</span>/<span class="hljs-attr">image.png</span>")} /&gt;</span></span>
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*6-5QCn6M6Z7Hu8YU_iSCKg.png" alt="Image" width="468" height="486" loading="lazy">
<em>Card (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#list-item"><strong>ListItem</strong></a></p>
<p>The <code>ListItem</code> molecule displays a <code>View</code> with an image, heading, and description. Of the three, the heading is mandatory. The style of this molecule differs according to the underlying platform.</p>
<pre><code class="lang-js">&lt;ListItem title=<span class="hljs-string">"Heading Only"</span> /&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ListItem</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Heading"</span> <span class="hljs-attr">description</span>=<span class="hljs-string">"And Description"</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ListItem</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Heading"</span> <span class="hljs-attr">description</span>=<span class="hljs-string">"Description"</span> <span class="hljs-attr">image</span>=<span class="hljs-string">{require(</span>"<span class="hljs-attr">.</span>/<span class="hljs-attr">path</span>/<span class="hljs-attr">to</span>/<span class="hljs-attr">an</span>/<span class="hljs-attr">image.png</span>")} /&gt;</span></span>
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*JbtPBYHdRFd1JrwIBJZTWg.png" alt="Image" width="467" height="432" loading="lazy">
<em>ListItems (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#notifications"><strong>Notification</strong></a></p>
<p>The <code>Notification</code> molecule displays a banner at the top of the page. The reference to the component is passed to the <code>NotificationManager</code>. Invoking the <code>showAlert</code> method of this manager, we can send the message to be displayed to the user.</p>
<p>Add the <code>Notification</code> as the very last element of the parent <code>View</code>.</p>
<pre><code class="lang-js">&lt;Notification ref={<span class="hljs-string">"alert"</span>} /&gt;
</code></pre>
<p>We will need to register this <code>Notification</code> molecule when the page mounts. This is to pass the reference of the <code>Notification</code> to the manager.</p>
<pre><code class="lang-js">componentDidMount() {
    NotificationBarManager.registerMessageBar(<span class="hljs-built_in">this</span>.refs.alert);
}
</code></pre>
<p>To clean up, we will also need to unregister this molecule as the page is unmounted.</p>
<pre><code class="lang-js">componentWillUnmount() {  
    NotificationBarManager.unregisterMessageBar();
}
</code></pre>
<p>To display the <code>Notification</code> bar, run the below method, passing the message to be displayed.</p>
<pre><code class="lang-js">NotificationBarManager.showAlert({  
    <span class="hljs-attr">message</span>: <span class="hljs-string">'Your alert message goes here'</span>
});
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*LoyUDfsV7iH8cfNCPBuH7A.gif" alt="Image" width="461" height="254" loading="lazy">
<em>Notification (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#floating-action-button"><strong>FloatingButton</strong></a></p>
<p>This molecule is equivalent to the Android Floating Action Button (FAB). It can be either a singular action or expand to display many actions.</p>
<p>If the FAB contains a singular action, we use the <code>onPress</code> property to pass the method to be run when the button is clicked.</p>
<pre><code class="lang-js">&lt;FloatingButton onPress={<span class="hljs-built_in">this</span>.handleShowNotification} /&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*luY2QUOdxc21FwdidH9brQ.gif" alt="Image" width="461" height="771" loading="lazy">
<em>FAB with singular action</em></p>
<p>If the FAB needs to expand to display many actions, and action array needs to be created. Each action object in the array needs to contain at a minimum:</p>
<ol>
<li>Unique <code>name</code></li>
<li><code>icon</code> or <code>image</code></li>
<li><code>position</code> from the top (starts at 1) when the FAB is expanded</li>
<li>method to run <code>onPress</code></li>
</ol>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> actions = [
    {
        <span class="hljs-attr">icon</span>: <span class="hljs-string">'help'</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">'bt_accessibility'</span>,
        <span class="hljs-attr">position</span>: <span class="hljs-number">2</span>,
        <span class="hljs-attr">onPress</span>: <span class="hljs-function">() =&gt;</span> Alert.alert(<span class="hljs-string">'Hello'</span>, <span class="hljs-string">'Accessibility'</span>)
    },
    {
        <span class="hljs-attr">icon</span>: <span class="hljs-string">'pin'</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">'bt_room'</span>,
        <span class="hljs-attr">position</span>: <span class="hljs-number">1</span>,
        <span class="hljs-attr">onPress</span>: <span class="hljs-function">() =&gt;</span> Alert.alert(<span class="hljs-string">'Hello'</span>, <span class="hljs-string">'Location'</span>)
    },
    {
        <span class="hljs-attr">icon</span>: <span class="hljs-string">'videocam'</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">'bt_videocam'</span>,
        <span class="hljs-attr">position</span>: <span class="hljs-number">3</span>,
        <span class="hljs-attr">onPress</span>: <span class="hljs-function">() =&gt;</span> Alert.alert(<span class="hljs-string">'Hello'</span>, <span class="hljs-string">'Video'</span>)
    }
];
</code></pre>
<p>We then pass the array to the <code>FloatingButton</code> in the property <code>actions</code>:</p>
<pre><code class="lang-js">&lt;FloatingButton actions={<span class="hljs-built_in">this</span>.actions} /&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*Y-AzQvQtemDwzT43aGpw8Q.gif" alt="Image" width="461" height="771" loading="lazy">
<em>FAB with multiple actions</em></p>
<h4 id="heading-organisms">Organisms</h4>
<p><strong>Form</strong></p>
<p>The <code>Form</code> organism is built of the form molecules, <code>FormInput</code>, <code>FormPicker</code>, <code>FormDatePicker</code>, and <code>FormTextArea</code>.</p>
<p>To render this organism, an array containing details of each field needs to be passed. The child components are rendered according to the <code>type</code> specified in each object.</p>
<p>The mapping is as follows:</p>
<ol>
<li>‘text’ — <code>FormInput</code></li>
<li>‘textarea’ — <code>FormTextArea</code></li>
<li>‘date’ — <code>FormDatePicker</code></li>
<li>‘picker’ — <code>FormPicker</code></li>
</ol>
<p>The object of each field can only contain the properties specified to the mapped field type. In simpler terms, an object of <code>type</code> ‘text’, must only contain the properties that the <code>FormInput</code> molecule accepts.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*sY8fbh-jSnI-oar9c1nhKg.png" alt="Image" width="468" height="722" loading="lazy">
<em>Form (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#cardlist"><strong>CardList</strong></a></p>
<p>This organism currently renders a read-only list of <code>Cards</code>, either horizontally or vertically. It requires an array of objects which have the same properties as a <code>Card</code> molecule.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> listData = [
    {
        <span class="hljs-attr">title</span>: <span class="hljs-string">"Heading 1"</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">"Description 1"</span>,
        <span class="hljs-attr">image</span>: <span class="hljs-built_in">require</span>(<span class="hljs-string">"./path/to/an/image.png"</span>)
    },
    {
        <span class="hljs-attr">title</span>: <span class="hljs-string">"Heading 2"</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">"Description 2"</span>,
        <span class="hljs-attr">image</span>: <span class="hljs-built_in">require</span>(<span class="hljs-string">"./path/to/an/image.png"</span>)
    },
    {
        <span class="hljs-attr">title</span>: <span class="hljs-string">"Heading 3"</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">"Description 3"</span>,
        <span class="hljs-attr">image</span>: <span class="hljs-built_in">require</span>(<span class="hljs-string">"./path/to/an/image.png"</span>)
    }
];
</code></pre>
<p>To render the list, pass the array above to the data property. Add the boolean property <code>horizontal</code>, if we wish for a horizontally scrolling list.</p>
<pre><code class="lang-js">&lt;CardList data={<span class="hljs-built_in">this</span>.listData} /&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CardList</span> <span class="hljs-attr">data</span>=<span class="hljs-string">{this.listData}</span> <span class="hljs-attr">horizontal</span> /&gt;</span></span>
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*rWLDdoHlAizf8n8zIOxJKg.gif" alt="Image" width="461" height="770" loading="lazy">
<em>CardList (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#listview"><strong>ListView</strong></a></p>
<p>This organism currently renders a read-only list of <code>ListItem’s</code> vertically. It requires an array of objects which have the same properties as a <code>ListItem</code> molecule. The same list used for a <code>CardList</code> can be used here as well.</p>
<pre><code class="lang-js">&lt;ListView data={<span class="hljs-built_in">this</span>.listData} /&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*U8raFMaggqk5jdbLyCdr-g.gif" alt="Image" width="461" height="770" loading="lazy">
<em>ListView (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#navbar"><strong>Header Navigation (NavBar)</strong></a></p>
<p>The <code>NavBar</code> organism is a page header that renders according to the underlying platform. It is rendered at the top of the page, right inside the page’s main <code>View</code> component.</p>
<p>To form the <code>NavBar</code>, all three child elements (<code>NavBarRight</code>, <code>NavBarLeft</code>, and <code>NavBarBody</code>) need to be included to align the elements correctly.</p>
<pre><code class="lang-js">&lt;NavBar&gt;  
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavBarLeft</span> /&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavBarBody</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Title<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">NavBarBody</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavBarRight</span>/&gt;</span></span>
&lt;/NavBar&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ehUzDGAIWWg3VSVnusCy1A.png" alt="Image" width="481" height="106" loading="lazy">
<em>NavBar with title only (Android)</em></p>
<p>We can also include buttons to the header with the <code>NavBarButton</code> component. This button can be added as children to the <code>NavBarRight</code> and <code>NavBarLeft</code> components.</p>
<p>The <code>NavBarButton</code> can be used in two ways:</p>
<ol>
<li>It has a property <code>type</code>, that accepts the values ‘back, ‘drawer’ and ‘search’. This renders the corresponding icons to each type by default.</li>
<li>We can create a custom button by including either <code>Texts</code>, <code>Icons</code> or <code>Images</code> as children in the <code>NavBarButton</code> component.</li>
</ol>
<pre><code class="lang-js">&lt;NavBar&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavBarLeft</span> &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">NavBarButton</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"drawer"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">NavBarLeft</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavBarBody</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Title<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">NavBarBody</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavBarRight</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">NavBarButton</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"heart"</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">NavBarButton</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">NavBarRight</span>&gt;</span></span>
&lt;/NavBar&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*gVBpFDczPEM84dY7LIvXzA.png" alt="Image" width="479" height="109" loading="lazy">
<em>NavBar with buttons (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#tabbar"><strong>Footer Navigation (TabBar)</strong></a></p>
<p>The <code>TabBar</code> organism is a page footer that renders according to the underlying platform. It is rendered at the very bottom of the page, right before the closing tag of the page’s main <code>View</code> component.</p>
<p>The TabBar contains multiple TabItems, depending on the number of pages in the tab navigation. A TabItem accepts either <code>Texts</code>, <code>Icons</code> or <code>Images</code> as children.</p>
<pre><code class="lang-js">&lt;TabBar&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TabItem</span> <span class="hljs-attr">active</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"heart"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Favorites<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">TabItem</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TabItem</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"add"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Add New<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">TabItem</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TabItem</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"camera"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Camera<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">TabItem</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">TabItem</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Icon</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"settings"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Settings<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">TabItem</span>&gt;</span></span>
&lt;/TabBar&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*5cXDFOxPpwZv9Q7_gGVmKA.png" alt="Image" width="479" height="56" loading="lazy">
<em>TabBar with text only (Android)</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ZvZcBROU_hdmQebebyhnXg.png" alt="Image" width="481" height="67" loading="lazy">
<em>TabBar with icons only (Android)</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*tLBwVpzKOTrjoNeuPMrJRA.png" alt="Image" width="479" height="89" loading="lazy">
<em>TabBar with icons and text (Android)</em></p>
<p><a target="_blank" href="https://github.com/99xt/first-born#pillbar"><strong>Pill Navigation (PillView)</strong></a></p>
<p>The <code>PillView</code> navigation is used to display different sections on a page. On Android, it renders as a header tab bar. On iOS, it renders as pills.</p>
<p>It requires two arrays to be passed to it, to successfully render the organism. One is a list of the scenes it will display. The second is the components to be displayed in the header (<code>PillBar</code>).</p>
<p>The pill scene only requires one key in the object. It is used to denote the scene to display on the view when the corresponding <code>PillItem</code> is clicked.</p>
<p>The pill header will require at least one of either Text, Icon or Image to render on the <code>PillItem</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pillScenes = [
    { <span class="hljs-attr">scene</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">CardList</span> <span class="hljs-attr">data</span>=<span class="hljs-string">{this.listData}</span> /&gt;</span></span> },
    { <span class="hljs-attr">scene</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ListView</span> <span class="hljs-attr">data</span>=<span class="hljs-string">{this.listData}</span> /&gt;</span></span> },
    { <span class="hljs-attr">scene</span>: 
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.innerContainer}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Form</span> <span class="hljs-attr">formElements</span>=<span class="hljs-string">{this.formElements}</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span> 
    }
];
</code></pre>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pillHeaders = [
    {
        <span class="hljs-attr">title</span>: <span class="hljs-string">'Card List'</span>,
        <span class="hljs-attr">icon</span>: <span class="hljs-string">"card"</span>
    },
    {
        <span class="hljs-attr">title</span>: <span class="hljs-string">'List View'</span>,
        <span class="hljs-attr">icon</span>: <span class="hljs-string">"list"</span>
    },
    {
        <span class="hljs-attr">title</span>: <span class="hljs-string">'Form'</span>,
        <span class="hljs-attr">icon</span>: <span class="hljs-string">"help"</span>
    }
];
</code></pre>
<p>We will then pass the two arrays to the <code>PillView</code> item like this:</p>
<pre><code class="lang-js">&lt;PillView pillHeaders={<span class="hljs-built_in">this</span>.pillHeaders} pillScenes={<span class="hljs-built_in">this</span>.pillScenes} /&gt;
</code></pre>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*R6vKLzsIROI1VyPFuzoC8g.gif" alt="Image" width="461" height="621" loading="lazy">
<em>PillView (Android)</em></p>
<p>And that is all the components <code>first-born</code> has to offer (so far…).</p>
<p>Once the code is a bit better assembled, we would end up with an app similar to this:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*vq0yVJovf5m2YC3aKqpM2A.gif" alt="Image" width="461" height="766" loading="lazy">
<em>Final implementation of all features</em></p>
<p>Give <code>first-born</code> a try and please do let me know how it goes for you.</p>
<p>Find the Demo repo <a target="_blank" href="https://github.com/samsam-026/firstBornExample">here</a>.</p>
<p>If you wish to see how first-born Navigation elements work with external navigation modules, have a look at the following repos;</p>
<p>React Navigation: <a target="_blank" href="https://github.com/samsam-026/first-born-react-navigation-example">first-born-react-navigation-example</a></p>
<p>React Native Router Flux: <a target="_blank" href="https://github.com/samsam-026/first-born-rnrf-example">first-born-rnrf-example</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to manage viewport intersection and input focus with custom React Hooks ]]>
                </title>
                <description>
                    <![CDATA[ By Dane David React Hooks have been here for a while, and there are many packages, recipes and discussions going on about the same. This article goes through a similar path. It explains through two custom hook implementations to show how well code ca... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-manage-viewport-intersection-and-input-focus-with-custom-react-hooks-1ec3403a8d80/</link>
                <guid isPermaLink="false">66c3539eb919d74bc820ad02</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 15 Apr 2019 15:39:14 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*itzX4RFL7kMtNv5UkvC_bA.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Dane David</p>
<p><a target="_blank" href="https://reactjs.org/docs/hooks-intro.html">React Hooks</a> have been here for a while, and there are many packages, recipes and discussions going on about the same. This article goes through a similar path. It explains through two custom hook implementations to show how well code can be reused. There may be libraries or gists that perform the exact (or maybe improved) functionality that this article explains. It always helps to write code tailored for your needs, code that you can reason about.</p>
<p>This article assumes basic understanding and knowledge of React and React hooks. If not, you can read the docs and find out more about the React Hooks API.</p>
<h4 id="heading-the-setup">The Setup</h4>
<p>Instead of being revealed at the end, we can first take a look at what functionality we’re trying to build. The live version of what we’re about to build is hosted here: <a target="_blank" href="https://danedavid.github.io/use-focus/">https://danedavid.github.io/use-focus</a>.</p>
<p>The app consists of a horizontal list of React components that can be scrolled through. Each component may be different or the same ( here, two different types of components are used, <em>only</em> to show that code can be reused across components ). The one thing they all have in common: an input field.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*EJfGOb35AOJ4j4M-AxVV6w.gif" alt="Image" width="640" height="281" loading="lazy">
<em>The element in the viewport is always the active element ( highlighted in green ) and has focus.</em></p>
<p><strong>Our Goal</strong>: Always make the element inside the viewport the “active” element. Give focus to the input field inside that component, throughout scrolling.</p>
<p>We can manage an <code>activeElement</code> state inside our root component, which stores an ID corresponding to the element active at any given time. The code for the root component is then:</p>
<p>Components <code>NumberInputFormElement</code> and <code>TextInputFormElement</code> are very similar components. The first one renders an <code>input[type="number"]</code>. While the latter renders a text input field. That’s the only difference.</p>
<h4 id="heading-useactiveonintersect">useActiveOnIntersect</h4>
<p>The first hook to be added is the one that will set the active element once the element reaches the viewport. That is, the hook <code>useActiveOnIntersect</code> must call <code>setActiveElement</code> passed from the parent, once the element is on the viewport. There is a well-known browser API for the same: <code>window.IntersectionObserver</code>. If you’re not familiar, I suggest you read more about it <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">here</a>.</p>
<p>The hook must basically create an instance of <code>IntersectionObserver</code> and listen for when it comes into view. We have given an <code>id=intersector</code> attribute for the outermost <code>div</code>. This <code>div</code> will act as the root element for IntersectionObserver. The element must listen to when it is totally (or at least 95%) inside this root element. We use the <code>useEffect</code> hook for registering the IntersectionObserver instance. And pass a callback function that invokes <code>setActiveElement</code> on the intersection ( in our case, when the intersection ratio is greater than 95% ). The code for <code>useActiveOnIntersect</code> is given below:</p>
<p>The hook does what it’s supposed to do: register an <code>observer</code> instance that listens for intersection with the root element, given in the options as <code>document.querySelector('#intersector')</code>, and invoke <code>setActiveElement</code> if the element is intersecting. <code>elementRef</code> is the React ref pointing to the DOM container element.</p>
<p>How does <code>setActiveElement</code> know <strong>which</strong> element is the active one? We’ll pass it from inside the component when we call this hook:</p>
<pre><code>useActiveOnIntersect(<span class="hljs-function">() =&gt;</span> setActiveElement(id), containerEl);
</code></pre><p>Here, <code>id</code> is the value to be set as the <code>activeElement</code> in <code>App</code> component. <code>containerEl</code> is the React ref referencing the input field’s container.</p>
<h4 id="heading-usefocusonactive">useFocusOnActive</h4>
<p>Now that we are sure that <code>activeElement</code> always points to the element that is inside the viewport ( root element ) at any given time, we need to make sure that the input field inside the component gets focus. Again, we use the <code>useEffect</code> hook for focusing the input field once it is active, and the cleanup function blurs the input field once it is not the active element anymore. The code is concise and straightforward:</p>
<p><code>inputRef</code> is the React ref pointing to the input field, and <code>active</code> is the active state of the containing element.</p>
<h4 id="heading-conclusion">Conclusion</h4>
<p>The code for a component that uses both these hooks is given below:</p>
<p>We have used <code>useRef</code> hook to create refs for container and input elements and pass it on to their respective hooks. The functionality can even be written inside a single hook. The reason behind writing two separate hooks is because each represents a different effect.</p>
<p>The complete code can be found here: <a target="_blank" href="https://github.com/danedavid/use-focus">https://github.com/danedavid/use-focus</a>.</p>
<p>Hope this article was helpful &amp; short! Go ahead and write your own custom React hook now!</p>
<p>If you liked the article, hit the clap button below. You can also follow me on medium or <a target="_blank" href="https://twitter.com/this_dane">twitter</a> for more!!</p>
<p>Happy coding…!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
