<?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[ Web Design - 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[ Web Design - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 05 Jun 2026 20:27:09 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/web-design/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ The Bad Website Club is Running a Free Responsive Web Design Bootcamp Based on freeCodeCamp ]]>
                </title>
                <description>
                    <![CDATA[ Hi everyone! We (Jess, Carmen, and Eda) are excited to announce the next installation of our free and online bootcamp. We support learners as they work their way through the freeCodeCamp Responsive We ]]>
                </description>
                <link>https://www.freecodecamp.org/news/bad-website-club-bootcamp-based-on-freecodecamp-rwd-cert/</link>
                <guid isPermaLink="false">69ce8df10ff860b6defc7074</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ bootcamp ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eda Eren ]]>
                </dc:creator>
                <pubDate>Thu, 02 Apr 2026 15:40:33 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/9a8913d9-9bc5-4e9e-9119-1d9d429578a0.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi everyone!</p>
<p>We (Jess, Carmen, and Eda) are excited to announce the next installation of our free and online bootcamp. We support learners as they work their way through the freeCodeCamp Responsive Web Design curriculum. The bootcamp will start Friday, April 24th, and will run for 10 weeks until Friday, July 3rd.</p>
<p>Here’s what to expect:</p>
<ul>
<li><p><strong>Live Streams:</strong> We’ll be streaming Monday to Friday at 15.00 UTC (<a href="https://everytimezone.com/s/6e8e42f0">you can check your timezone here</a>), where we’ll go through the course material together on our <a href="https://www.youtube.com/@badwebsiteclub">YouTube channel</a>, on <a href="https://www.twitch.tv/jesslynnrose">Jess' Twitch channel</a> and <a href="https://www.twitch.tv/hola_soy_milk_">Carmen's Twitch channel</a>. It’s also a chance to ask your questions! If you can’t join us live, the streams will be available offline to watch later.</p>
</li>
<li><p><strong>Guest Sessions:</strong> We’ll expand on our studies with guest sessions where professionals working in software engineering and related fields will talk about their craft.</p>
</li>
<li><p><strong>Community:</strong> To support each other and work together, we have a dedicated Discord channel in the freeCodeCamp Discord server (you can join here: <a href="https://discord.gg/KVUmVXA">https://discord.gg/KVUmVXA</a>) to help you establish better connections with other learners working on freeCodeCamp material. We’ll also be including shared notes on our <a href="https://badwebsite.club">website</a>.</p>
</li>
<li><p><strong>Calendar:</strong> We have a <a href="https://badwebsite.club/calendars/spring-2026-lessons.ics">shared calendar</a> of lessons we’ll be covering with a supportive and friendly group of learners alongside you.</p>
</li>
<li><p><strong>Newsletter:</strong> There’s no signup needed, but if you want weekly emails, you can also <a href="https://buttondown.com/bad-website-club">sign up for our newsletter</a>.</p>
</li>
</ul>
<h2 id="heading-how-does-the-bootcamp-work">How Does the Bootcamp Work?</h2>
<p>Bad Website Club bootcamps have been running for a while, so if you've joined us in the past, this one is going to feel a little different.</p>
<p>As the freeCodeCamp course material has expanded, we have adapted our learning structure to reflect what’s in it.</p>
<p>We’re experimenting with a flipped classroom model, where learners do pre-reading and more solo work before classes to come into streamed sessions, prepared to support each other’s learning.</p>
<p>Also, learners will be able to contribute to shared lesson notes which we’ll be going over in unit reviews. We’ll be talking through some (not all!) of the workshop steps and offer space for Q&amp;A in our live streams.</p>
<p>The labs and certification projects need to be done as solo work, but we’ll be looking at how to approach them together on streams and covering them in Q&amp;As.</p>
<p>We’ll be moving fast, but there are no fixed deadlines! If you need more time, your progress will be saved on your freeCodeCamp account. Also, the videos and our Discord are available after the bootcamp ends.</p>
<p>Note that the bootcamp doesn't offer job placement support or 1:1 instructor support for learners due to the size and global distribution of our learners. But we’ll help you learn the skills that prepare you to pursue opportunities on your own.</p>
<h2 id="heading-who-we-are">Who We Are</h2>
<p>Bad Website Club has been running free and online developer education programs since 2020. It's run by a small volunteer team (<a href="https://jessica.tech/">Jessica Rose</a>, <a href="https://carmenh.dev/">Carmen Huidobro</a>, and <a href="https://edaeren.com/">Eda Eren</a> – also thank you to wonderful <a href="https://kirionearth.com/">Kiri</a> who made all the art!). We focus on learning and experimenting over perfection, and believe that the web can be better when it includes everyone.</p>
<p>Also, it really is free: there’s no way to pay for it.</p>
<p>If you want to join us, you can <a href="https://badwebsite.club/calendars/spring-2026-lessons.ics">download or subscribe to the full lesson calendar</a> (for Google Calendar, use the iCal feed with <a href="https://support.google.com/calendar/answer/37100?hl=en">these subscription instructions</a>), follow us on our <a href="https://www.youtube.com/@badwebsiteclub">YouTube channel</a>, on <a href="https://www.twitch.tv/jesslynnrose">Jess' Twitch channel</a> and <a href="https://www.twitch.tv/hola_soy_milk_">Carmen's Twitch channel</a>. You can also sign up for our weekly newsletter for lesson notes, show and tell projects, extra resources, and more.</p>
<p>Hope to see you soon!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Portfolio Website Using Figma and AI Tools – A Guide for Developers ]]>
                </title>
                <description>
                    <![CDATA[ Ever since my article on How to Become a Full Stack Developer and Get a Job in 2025 went viral, I’ve received countless DMs, emails, and even WhatsApp messages from readers. People have been asking about everything from learning to code and mastering... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-portfolio-website-using-figma-and-ai-tools/</link>
                <guid isPermaLink="false">691b93910ca13a7c59ae7a34</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ figma ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ portfolio ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Prankur Pandey ]]>
                </dc:creator>
                <pubDate>Mon, 17 Nov 2025 21:28:49 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763156337448/4d944077-b800-4bfd-bb70-645777eb00a2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Ever since my article on <a target="_blank" href="https://www.freecodecamp.org/news/become-a-full-stack-developer-and-get-a-job/">How to Become a Full Stack Developer and Get a Job in 2025</a> went viral, I’ve received countless DMs, emails, and even WhatsApp messages from readers. People have been asking about everything from learning to code and mastering system design to web design and how AI fits into modern development.</p>
<p>I’ve been taking it one topic at a time. My last piece on system design principles received great feedback, and that encouragement has kept me going.</p>
<p>Lately, I’ve developed a deep interest in UI/UX design – not just out of curiosity, but because so many readers have been requesting a detailed guide. They want one that explains how to learn web design, how to apply it to real-world projects, and how AI is reshaping the field.</p>
<p>Looking back, my journey started six years ago as a software tester. From there, I transitioned into full-stack development, then DevOps. I also explored data analysis, and today I manage a full-time freelancing career alongside my farming work.</p>
<p>One thing I’ve learned along the way is that a strong portfolio can take you to places you’d never imagined.</p>
<p>I’ve had a portfolio for years, but now I’m completely rebuilding it from scratch to make it cleaner, smarter, and more reflective of who I’ve become as a developer.</p>
<p>In this tutorial, I’ll walk you through how I created my new portfolio and show you how you can build yours too – with the right structure, design, and a touch of copywriting magic to make it stand out.</p>
<h3 id="heading-what-well-cover">What We’ll Cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-portfolio-website-and-why-do-you-need-one">What is a Portfolio Website and Why Do You Need One?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-important-portfolio-website-components">Important Portfolio Website Components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-make-your-portfolio-website-stand-out">How to Make Your Portfolio Website Stand Out</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-figma-to-design-your-own-portfolio">How to use Figma to Design Your Own Portfolio</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tools-for-figma-to-code-generation">Tools for Figma to Code Generation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-copywriting-for-your-portfolio">Copywriting for Your Portfolio</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-benchmarks-for-a-portfolio-website">Testing Benchmarks for a Portfolio Website</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-hosting-your-portfolio">Hosting Your Portfolio</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-your-portfolio-effectively">How to Use Your Portfolio Effectively</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-qampa">Q&amp;A</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-notes">Final Notes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-a-portfolio-website-and-why-do-you-need-one">What is a Portfolio Website and Why Do You Need One?</h2>
<p>A portfolio website is your own space on the internet where you can proudly show your best work, projects, and achievements. Think of it as your digital résumé, but far more visual and personal. Instead of just listing your skills or job titles, it lets people actually see what you’ve built, designed, or created, and this tells your story better than any document can.</p>
<p>It helps employers, clients, or collaborators understand your skills, experience, and creativity at a glance. While it’s beneficial for designers, developers, writers, and photographers, anyone who wants to share their work online can create one, from students and freelancers to business professionals.</p>
<p>Here’s why having a portfolio website matters:</p>
<ul>
<li><p><strong>A collection of your best work:</strong> like a gallery where you keep your most impressive projects, artwork, or achievements all in one place.</p>
</li>
<li><p><strong>Your online identity:</strong> It’s your personal brand, showing who you are, what you do, and what makes your work stand out.</p>
</li>
<li><p><strong>A way to showcase your skills:</strong> Through images, videos, and live demos, it give people a clear picture of your talent and creativity.</p>
</li>
<li><p><strong>An open door for opportunities:</strong> People can visit your site, explore your work, and contact you directly for jobs, collaborations, or freelance work.</p>
</li>
<li><p><strong>A tool for career growth:</strong> A well-built portfolio helps you attract clients, get noticed by employers, and open doors to new partnerships.</p>
</li>
</ul>
<p>In simple words, your portfolio website is your professional story told visually – a mix of your work, passion, and personality that helps the world see what you’re capable of.</p>
<h2 id="heading-important-portfolio-website-components">Important Portfolio Website Components</h2>
<p>Now that we know why a portfolio website matters, let’s look at the key components that make it stand out. Each part plays a role in showing who you are, what you can do, and how you can help others.</p>
<p>Since I’m a developer, and the people who have reached out to me are mostly tech enthusiasts, here I’ll give a technical portfolio example. But you can apply the learnings from this guide to build any type of portfolio for any niche/business.</p>
<h3 id="heading-1-home-page-the-first-impression">1. Home Page: The First Impression</h3>
<p>Your homepage is like the front door to your digital world. It should quickly tell visitors who you are, what you do, and why you’re worth hiring or collaborating with. Keep it clean, simple, and welcoming: just a few strong lines about your skills and what kind of projects you work on.</p>
<p>Tip: Use a short headline like “Hi, I’m Prankur – I build fast, user-friendly web apps.”</p>
<h3 id="heading-2-about-section-your-story">2. About Section: Your Story</h3>
<p>This is where you make your connection with the audience. Share your journey: how you started, what drives you, and what kind of problems you love solving. Keep it conversational and honest. People love working with real humans, not buzzwords.</p>
<p>Tip: Add a professional but friendly photo (optional) here to make it more personal.</p>
<h3 id="heading-3-projects-work-section-show-dont-just-tell">3. Projects / Work Section: Show, Don’t Just Tell</h3>
<p>This is the heart of your portfolio. List your best projects – the ones that represent your strongest skills and the kind of work you want to keep doing. Each project should include:</p>
<ul>
<li><p>A short description of what it is.</p>
</li>
<li><p>The tools or technologies you used.</p>
</li>
<li><p>The challenge you solved.</p>
</li>
<li><p>A screenshot or live demo link.</p>
</li>
<li><p>GitHub link so that people can see how you code</p>
</li>
</ul>
<p>Tip: 3–6 strong projects are better than 15 average ones. If you’re actively contributing to open source, you should add that to your portfolio, too.</p>
<h3 id="heading-4-case-studies-tell-the-story-behind-the-work">4. Case Studies: Tell the Story Behind the Work</h3>
<p>Case studies take your projects one step further. They explain your thinking process and how you understood the client’s problem, what steps you took, and what results you achieved. This helps potential employers or clients see your problem-solving skills, not just your designs or code.</p>
<p>Tip: Keep it short and focus on the “before → after” transformation.</p>
<h3 id="heading-5-skills-amp-tools-section">5. Skills &amp; Tools Section</h3>
<p>List your key technical and creative skills, like HTML, CSS, JavaScript, React, Figma, or AI.<br>You can group them as:</p>
<ul>
<li><p>Frontend Tools</p>
</li>
<li><p>Backend Tools</p>
</li>
<li><p>Design Tools</p>
</li>
<li><p>AI or Productivity Tools</p>
</li>
</ul>
<p>Tip: Keep the list focused and highlight the tools you actually use, not every tool you’ve ever tried.</p>
<h3 id="heading-6-testimonials-social-proof-optional">6. Testimonials: Social Proof (Optional)</h3>
<p>People trust people. Include a few quotes or short testimonials from clients, teammates, or mentors who can vouch for your skills and professionalism. It instantly builds trust and credibility.</p>
<p>If you are just starting, you can add this section later on, as initially you won’t have testimonials. Once you start working, you can politely ask your clients to give their feedback on your work. Just make sure to get their permission to add it to your site.</p>
<p>Tip: Ask for a 2–3 sentence testimonial right after finishing a project.</p>
<h3 id="heading-7-blog-or-articles-section-optional">7. Blog or Articles Section (Optional)</h3>
<p>If you write tutorials or share knowledge, add a blog section. It helps you stand out as someone who not only builds but also teaches and communicates ideas clearly. It also boosts SEO and keeps your site fresh.</p>
<p>Tip: Even 2–3 strong, educational articles can make a huge difference.</p>
<h3 id="heading-8-contact-section-make-it-easy-to-reach-you">8. Contact Section: Make It Easy to Reach You</h3>
<p>Your contact page should be simple, visible, and welcoming. Include your email, social links (LinkedIn, GitHub, X/Twitter), and maybe a contact form. You can also add a small call to action like:</p>
<blockquote>
<p>“Have a project in mind? Let’s connect.”</p>
</blockquote>
<p>Tip: Place your contact link in the main menu. Don’t hide it.</p>
<h3 id="heading-9-resume-downloadable-cv-optional">9. Résumé / Downloadable CV (Optional)</h3>
<p>If you’re job-hunting, include a link to download your latest résumé. You can also add a “quick summary” of your experience, education, and certifications directly on the website.</p>
<h3 id="heading-10-call-to-action-cta">10. Call to Action (CTA)</h3>
<p>Every great portfolio ends with a nudge – a simple next step for your visitor. It could be:</p>
<ul>
<li><p>“Let’s build something amazing together.”</p>
</li>
<li><p>“Hire me for your next project.”</p>
</li>
<li><p>“Check out my latest work.”</p>
</li>
</ul>
<p>A clear CTA can help turn a visitor into a lead or follower.</p>
<p>Your portfolio is not just a gallery. It’s a storytelling tool. It tells the world what you can do, how you think, and what makes you unique. Make sure every section serves a purpose, looks clean, and reflects your real personality.</p>
<h2 id="heading-how-to-make-your-portfolio-website-stand-out">How to Make Your Portfolio Website Stand Out</h2>
<p><strong>1. Showcase Your Best Work</strong><br>Only include your strongest and most relevant projects. Quality matters more than quantity. A few great examples of your work will create a much better impression than a long list of average ones.</p>
<p><strong>2. Use High-Quality Images and Videos</strong><br>Make sure your work looks clear and professional. Good visuals instantly catch attention and show that you care about presentation. Use clean screenshots, mockups, or short demo videos.</p>
<p><strong>3. Write Clearly and Keep It Short</strong><br>Explain your work and skills in simple, easy-to-read language. Avoid long paragraphs — most visitors just skim. A few lines that get straight to the point are enough.</p>
<p><strong>4. Tell Your Story</strong><br>Use your “About Me” section to share your journey — how you started, what you love building, and what kind of work you enjoy most. People connect more with stories than with just titles or resumes.</p>
<p><strong>5. Keep Navigation Simple</strong><br>Make sure visitors can easily find your projects, contact info, and other key details. A clean menu and clear layout help people focus on your work instead of figuring out where to click.</p>
<p><strong>6. Keep It Updated</strong><br>Whenever you finish a new project or learn a new skill, add it to your portfolio. An up-to-date portfolio shows that you’re active, learning, and growing in your field.</p>
<p><strong>7. Optimise for SEO</strong><br>Use the right keywords — the ones people might type when searching for your kind of work (like “frontend developer” or “Figma to code expert”). This helps your site appear in search results. Many AI-powered website builders can assist with basic SEO setup.</p>
<h2 id="heading-how-to-use-figma-to-design-your-own-portfolio">How to Use Figma to Design Your Own Portfolio</h2>
<p>Designing your own portfolio might sound intimidating at first, but tools like <strong>Figma</strong> make the process surprisingly intuitive – even if you’re not a professional designer. With Figma, you can visually plan every section of your portfolio before turning it into a live website.</p>
<p>I’ve been learning web design and using Figma for a long time for my client projects. But here, I didn’t build the entire portfolio from scratch. I used Figma’s design inspiration library to get some ideas, and I built the portfolio based on that.</p>
<p>Let’s walk through how you can do that, step by step, using the layout shown below as an example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763135985349/8cb05eb4-7562-4845-992e-9829ebadf6a4.png" alt="example-portfolio" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-1-start-with-a-wireframe">1. Start With a Wireframe</h3>
<p>Before adding colours or fancy visuals, begin with a simple wireframe. It’s basically a rough sketch of your portfolio layout.</p>
<p>In Figma, you can create frames for each section you want on your site:</p>
<ul>
<li><p>Hero section (your name, title, and call-to-action buttons)</p>
</li>
<li><p>“What I Do Best” or skills</p>
</li>
<li><p>Tech stack</p>
</li>
<li><p>Featured projects</p>
</li>
<li><p>Blog or article previews</p>
</li>
<li><p>Services and pricing</p>
</li>
<li><p>Contact form</p>
</li>
</ul>
<p>This helps you get the structure right before focusing on design. Don’t worry about fonts or images yet – just boxes and text placeholders are enough.</p>
<p>Here’s a sample wireframe I created to visualise how everything should look before moving into Figma. It’s always a good idea to sketch or plan your design on paper first, as it helps you get a clear picture of the layout and refine details like colours, fonts, and spacing early on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762753167965/584a137e-6414-4ce6-ad1e-0408d040003f.png" alt="wireframe-figma" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Once the wireframe is ready, you can start adding your preferred colours, typography, and images to bring the design to life. If you want to go a step further and understand how to choose the right colour palettes and fonts, it’s worth exploring <strong>design psychology</strong> — it plays a huge role in how people perceive your work.</p>
<h3 id="heading-2-add-visual-hierarchy-and-colour">2. Add Visual Hierarchy and Colour</h3>
<p>Once your structure feels solid, start adding typography and colour to create a visual hierarchy. This helps the viewer’s eyes know where to focus first.</p>
<p>For example, in the sample design above, the <strong>hero section</strong> (at the top) instantly grabs attention with bold typography (“I build things for the web”) and a subtle background/hero image.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763135295720/87dfa444-1e80-45b2-8e57-7f88971a4742.png" alt="visual-hierachy-and-color-figma" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Use Figma’s colour styles to define a consistent palette. Try using about 3 to 4 shades that complement each other. Keep it minimal and professional. For text, you can choose neutral fonts like Poppins, Inter, or Roboto, which look great on both dark and light themes.</p>
<h3 id="heading-3-create-components-for-reuse">3. Create Components for Reuse</h3>
<p>Figma allows you to turn recurring UI elements like buttons, cards, and tags into components. In the portfolio example here, notice how every project card, article preview, and pricing box follows the same layout. By creating a single card component and reusing it, you can easily maintain consistency and update everything in one go later.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763135361258/41a8fdfe-d384-4039-8ab1-1a2499e58363.png" alt="components-reuse-figma" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In this design, I will be using a blog featuring component multiple times, so instead of designing it again and again, I have made it once, and I am now using it multiple times.</p>
<h3 id="heading-4-add-your-content-and-images">4. Add Your Content and Images</h3>
<p>Now that your base design is ready, it’s time to make it personal. You can go ahead and replace placeholders with:</p>
<ul>
<li><p>Your best project screenshots (use mockups if needed),</p>
</li>
<li><p>Professional headshot or relevant visuals,</p>
</li>
<li><p>Real content, like your bio, skills, and service details.</p>
</li>
</ul>
<p>Make sure you keep the spacing clean. It ensures all sections stay neatly aligned, even when you adjust or add new elements later.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763135295720/87dfa444-1e80-45b2-8e57-7f88971a4742.png" alt="add-your-content-figma" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In this hero section, I have used my name and colour and font of my choice on the left, and you can see the <strong>Styles</strong> showing all the colours I have used across the project.</p>
<h3 id="heading-5-create-interactive-prototypes">5. Create Interactive Prototypes</h3>
<p>Before exporting your design, use Figma’s <strong>Prototype Mode</strong> to link different pages together – for example, make “Projects” in the top navigation scroll smoothly to your project section. This gives you a working demo to test how users will experience your portfolio before you even write a single line of code.</p>
<p>You can also share this prototype with friends or mentors for quick feedback.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763135522546/1ef82103-13b6-4e9e-b102-b1c8cc20d03f.png" alt="create-interactive-prototype-figma" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-6-export-or-hand-off-for-development">6. Export or Hand Off for Development</h3>
<p>After testing your design in Prototype Mode when you’re satisfied, the final step is the <strong>handoff</strong>. Use the Export panel to download all required assets (icons, logos, images) in their correct formats. Then share the Figma file and go to <strong>Dev Mode</strong>, where you can inspect typography, spacing, sizes, and colour values. These exported assets and inspected specs are what developers use to create the live HTML/CSS code.</p>
<p>Note: The Dev Mode in Figma allows you to inspect CSS and export your stuff easily. Since I don’t have a paid Figma plan, I can’t show inspecting and exporting.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763134948092/1f98417c-5120-48ac-b302-84d5234a7b95.png" alt="figma-handoff" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Designing your portfolio in Figma gives you full freedom over layout, colour choices, and how you present your personality. Keep it simple, prioritise usability, and design with clarity. Once the layout is complete and tested, converting it into a functional site becomes straightforward.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763138419092/978156ba-dbb3-4a6e-bcb8-3a0c7ff66e0d.png" alt="figma-auto-layout" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You can also use auto layout just by right-clicking on the design section components.</p>
<p>Auto Layout allows designers to define rules for spacing, direction, padding, and alignment of elements. This ensures layouts like buttons, lists, and cards instantly adapt (scale/shrink) to content changes or different screen sizes without manual adjustments.</p>
<p>Once you’ve built and tested your Figma layout, converting it into code becomes the easy part.</p>
<h2 id="heading-tools-for-figma-to-code-generation">Tools for Figma to Code Generation</h2>
<p>By the time you’re done with the wireframe and colours, and your portfolio is live on Figma, it’s time to convert that Figma design into code. There are two ways to do so:</p>
<ul>
<li><p>Manual Method</p>
</li>
<li><p>AI Method</p>
</li>
</ul>
<h3 id="heading-how-to-manually-convert-figma-designs-to-code">How to Manually Convert Figma Designs to Code</h3>
<p>When you design a website or app in Figma, the next big step is turning that design into working code. Traditionally, developers have done this manually: inspecting each element, writing HTML, CSS, and then refining the layout in frameworks like React or Tailwind CSS.</p>
<p>It’s important to understand <strong>how this process is normally done by hand</strong>. This is the foundation that every frontend developer relies on — and it’s also what helps you evaluate and improve AI-generated code later.</p>
<p>When you design a website or app in Figma, the next step is to translate that visual layout into real HTML, CSS, and JavaScript. Developers usually start by examining each element in the design – its size, spacing, typography, colour, and layout rules – and manually rebuilding it in code.</p>
<h3 id="heading-exporting-visual-assets">Exporting Visual Assets</h3>
<p>Using Figma’s <em>Export</em> panel, you download only what needs to be recreated visually in code:</p>
<ul>
<li><p>icons</p>
</li>
<li><p>illustrations</p>
</li>
<li><p>logos</p>
</li>
<li><p>images or thumbnails</p>
</li>
</ul>
<p>Most structural elements (buttons, cards, sections, containers) are <strong>not</strong> exported – you’ll need to build them using HTML and CSS.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763127453427/38bbbdef-270c-4157-8a2d-8fd8591426ea.png" alt="figma-export-panel" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-rebuilding-the-layout-with-html-and-css">Rebuilding the Layout with HTML and CSS</h3>
<p>You’ll recreate the page section by section:</p>
<ul>
<li><p>Setting up the HTML structure</p>
</li>
<li><p>Adding Flexbox or CSS Grid for layouts</p>
</li>
<li><p>Applying typography exactly as specified in Figma</p>
</li>
<li><p>Matching spacing using padding, margins, and gaps</p>
</li>
<li><p>Defining colours using the hex codes from the Figma Inspector</p>
</li>
</ul>
<p>If you’re using Tailwind CSS, this becomes a matter of applying the right utility classes, but the logic remains the same: <em>everything is recreated manually</em>.</p>
<p>Once you have your Figma layout ready, the real work happens inside your code editor (which for me is VS Code). Here’s how developers traditionally rebuild the UI one section at a time.</p>
<h3 id="heading-set-up-your-project-structure">Set Up Your Project Structure</h3>
<p>In VS Code, create your project structure. It’ll look something like this:</p>
<pre><code class="lang-plaintext">project/
 ├─ index.html
 ├─ styles.css
 ├─ /assets
 │    ├─ logo.svg
 │    ├─ hero-image.png
 │    └─ icons/
</code></pre>
<p>If you’re using React, this becomes the structure:</p>
<pre><code class="lang-bash">src/
 ├─ App.jsx
 ├─ components/
 ├─ index.css
 ├─ assets/
</code></pre>
<p>This structure mirrors what you saw in Figma: each major design section becomes a container or component.</p>
<h3 id="heading-write-the-html-structure-section-by-section">Write the HTML Structure Section-by-Section</h3>
<p>Now, you’ll look at the Figma frame and convert it to raw markup.</p>
<p>As an example, let’s look at the Hero Section.</p>
<p>Figma frame shows:</p>
<ul>
<li><p>a headline</p>
</li>
<li><p>subtext</p>
</li>
<li><p>a button</p>
</li>
<li><p>an illustration</p>
</li>
</ul>
<p>So your HTML becomes this:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hero"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hero-content"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Modern UI for Everyone<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>Beautiful designs built for speed and accessibility.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cta-btn"</span>&gt;</span>Get Started<span class="hljs-tag">&lt;/<span class="hljs-name">button</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">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"assets/hero-image.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Hero illustration"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"hero-img"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
</code></pre>
<p>You're essentially mapping each Figma layer onto an HTML element.</p>
<h3 id="heading-build-layouts-using-flexbox-or-grid">Build Layouts Using Flexbox or Grid</h3>
<p>In Figma, layouts are visual. In HTML/CSS, you must <strong>translate</strong> the layout rules.</p>
<p>If Figma shows two columns (text + image), you’ll use Flexbox:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.hero</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: space-between;
}
</code></pre>
<p>If Figma has a 3-card layout, you’ll use Grid:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.features</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">3</span>, <span class="hljs-number">1</span>fr);
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">2rem</span>;
}
</code></pre>
<p>You literally reconstruct the layout <em>from scratch</em> by interpreting the Figma frame’s structure.</p>
<h3 id="heading-apply-typography-exactly-as-in-figma">Apply Typography Exactly as in Figma</h3>
<p>Next, you’ll go to Figma, select a text layer, and check the <strong>Inspector</strong>:</p>
<ul>
<li><p>Font family: Inter</p>
</li>
<li><p>Font size: 36px</p>
</li>
<li><p>Line height: 44px</p>
</li>
<li><p>Font weight: 700</p>
</li>
<li><p>Letter spacing: -1%</p>
</li>
</ul>
<p>Then recreate it like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.hero</span> <span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Inter'</span>, sans-serif;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">36px</span>;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">44px</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">700</span>;
  <span class="hljs-attribute">letter-spacing</span>: -<span class="hljs-number">0.01em</span>;
}
</code></pre>
<p>This is why developers need to know their fundamentals: AI tools often miss these fine details.</p>
<h3 id="heading-recreate-spacing-with-padding-margins-gaps">Recreate Spacing With Padding, Margins, Gaps</h3>
<p>In Figma, spacing is visual. But in code, you must <em>calculate and apply</em> it.</p>
<p>Example Figma spacing:</p>
<ul>
<li><p>Padding inside a button: 16px vertical / 32px horizontal</p>
</li>
<li><p>Margin below a heading: 24px</p>
</li>
<li><p>Gap between elements: 32px</p>
</li>
</ul>
<p>So you write this code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.cta-btn</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">16px</span> <span class="hljs-number">32px</span>;
}

<span class="hljs-selector-class">.hero</span> <span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">24px</span>;
}

<span class="hljs-selector-class">.hero-content</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">32px</span>;
}
</code></pre>
<p>Everything must match the design. And in this case, spacing is what makes UI look polished.</p>
<h3 id="heading-apply-colours-using-figma-hex-codes">Apply Colours Using Figma Hex Codes</h3>
<p>In Figma Inspector:</p>
<ul>
<li><p>Primary Blue → <code>#4A78FF</code></p>
</li>
<li><p>Background → <code>#F8FAFC</code></p>
</li>
<li><p>Text → <code>#1A1A1A</code></p>
</li>
</ul>
<p>In your CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#F8FAFC</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#1A1A1A</span>;
}

<span class="hljs-selector-class">.cta-btn</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#4A78FF</span>;
  <span class="hljs-attribute">color</span>: white;
}
</code></pre>
<p>You’ll need to manually copy each hex code into CSS, as this is where accuracy matters.</p>
<h3 id="heading-if-using-tailwind-apply-utility-classes-instead-of-writing-css">(If Using Tailwind) Apply Utility Classes Instead of Writing CSS</h3>
<p>Switching back and forth between your Figma design and a separate CSS file can slow down your whole workflow. Tailwind CSS solves this by letting you write styles right inside your HTML using small, reusable utility classes.</p>
<p>In this section, you’ll learn how to take the exact pixel values you see in the <strong>Figma Inspector</strong> and turn them into Tailwind utilities.</p>
<h4 id="heading-step-1-understand-tailwinds-spacing-scale">Step 1: Understand Tailwind’s Spacing Scale</h4>
<p>Tailwind doesn’t use raw pixel values. Instead, it uses a consistent spacing scale, usually based on a 4px grid.</p>
<p>Here’s the simple rule: Take the pixel value from Figma, divide by 4, and that number becomes your Tailwind utility.</p>
<p>Example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Figma</td><td>Tailwind</td><td>Meaning</td></tr>
</thead>
<tbody>
<tr>
<td><code>margin-top: 32px</code></td><td><code>mt-8</code></td><td>32 ÷ 4 = 8 → so the class is <code>mt-8</code></td></tr>
</tbody>
</table>
</div><p>Prefixes you should know:</p>
<ul>
<li><p><code>m</code> = margin</p>
</li>
<li><p><code>p</code> = padding</p>
</li>
<li><p><code>t</code>, <code>b</code>, <code>l</code>, <code>r</code> = top, bottom, left, right</p>
</li>
<li><p><code>x</code> = horizontal (left + right)</p>
</li>
<li><p><code>y</code> = vertical (top + bottom)</p>
</li>
</ul>
<h4 id="heading-step-2-converting-complex-padding">Step 2: Converting Complex Padding</h4>
<p>If your Figma element uses different padding for X and Y, convert each side separately.</p>
<p>Example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Figma</td><td>Tailwind</td><td>Meaning</td></tr>
</thead>
<tbody>
<tr>
<td><code>padding: 16px 32px</code></td><td><code>py-4 px-8</code></td><td>16 ÷ 4 = 4 → <code>py-4</code></td></tr>
<tr>
<td>32 ÷ 4 = 8 → <code>px-8</code></td><td></td></tr>
</tbody>
</table>
</div><h4 id="heading-step-3-converting-font-sizes">Step 3: Converting Font Sizes</h4>
<p>Tailwind doesn’t use pixel sizes for fonts. Instead, it uses semantic names – almost like T-shirt sizes.</p>
<p>Example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Figma Font Size</td><td>Tailwind Class</td><td>Meaning</td></tr>
</thead>
<tbody>
<tr>
<td><code>36px</code></td><td><code>text-4xl</code></td><td>Tailwind’s <code>4xl</code> matches 36px in the default scale</td></tr>
</tbody>
</table>
</div><p>This encourages typography consistency, instead of manually choosing random font sizes.</p>
<h4 id="heading-why-this-method-is-so-fast">Why This Method Is So Fast</h4>
<p>Once you get used to it, the workflow becomes second nature:</p>
<pre><code class="lang-powershell">Figma value → divide by <span class="hljs-number">4</span> → apply Tailwind <span class="hljs-class"><span class="hljs-keyword">class</span></span>
</code></pre>
<p>No switching files. No naming CSS classes. No extra stylesheet bloat.</p>
<p>Just fast, direct, design-to-code translation.</p>
<h4 id="heading-try-it-yourself">Try It Yourself</h4>
<p>Open a Figma component (like a button or a card) and check its spacing, padding, and font size in the Inspector. Then convert everything using the simple rules above.</p>
<p>Before long, you’ll be turning Figma designs into clean Tailwind code in seconds.</p>
<p>You still translate Figma to code manually.</p>
<p>Alright, back to our workflow:</p>
<h3 id="heading-making-it-responsive">Making It Responsive</h3>
<p>You check how the design should behave on different screen sizes:</p>
<ul>
<li><p>stacking vs. side-by-side layouts</p>
</li>
<li><p>font scaling</p>
</li>
<li><p>spacing adjustments</p>
</li>
<li><p>collapsing navigation or rearranging grids</p>
</li>
</ul>
<p>This requires writing responsive styles and breakpoints, which AI tools can attempt but rarely perfect.</p>
<h3 id="heading-why-the-manual-way-is-important">Why the Manual Way Is Important</h3>
<p>Even though it takes more time, this approach teaches fundamentals that AI tools simply can’t replace:</p>
<ul>
<li><p>How spacing systems work</p>
</li>
<li><p>How components behave in real browsers</p>
</li>
<li><p>How layout changes across devices</p>
</li>
<li><p>How to optimise for performance and accessibility</p>
</li>
</ul>
<p>These skills allow you to <strong>inspect code intelligently</strong> and improve it wherever needed, which is <em>almost always necessary</em>, no matter which tool you use.</p>
<h3 id="heading-how-to-use-ai-tools-to-convert-figma-designs-to-code-optional">How to Use AI Tools to Convert Figma Designs to Code (Optional)</h3>
<p>To speed up this process, you can now use AI-powered and automated Figma-to-code tools. These tools analyse the Figma file and instantly generate code that you can integrate into your tech stack.</p>
<p>There are multiple tools available in the market, like V0, Builder.io, and Kombai.</p>
<ul>
<li><p><a target="_blank" href="https://v0.dev">V0</a> is A Vercel project focused on fast UI generation, integrated with Next.js workflows.</p>
</li>
<li><p><a target="_blank" href="https://Builder.io">Builder.io</a> is visual CMS with Figma integration and a visual editor that can export components for web apps.</p>
</li>
<li><p><a target="_blank" href="https://kombai.com">Kombai</a> is an IDE extension that converts selected Figma frames into React/NextJS/React Native code and offers repo-aware features.</p>
</li>
</ul>
<h4 id="heading-building-live">Building Live</h4>
<p>For demonstration purposes, I’ll be using Kombai, a VS Code extension. And since most of us developers spend a lot of time inside VS Code, it’s the perfect place to test it out.</p>
<p>To install it in VS Code, simply open the Extensions Marketplace, search for 'kombai', click 'Install' and open the extension.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761314891808/1e28092b-9011-476d-869d-08ce6b675766.png" alt="Kombai agent vs code install " class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Now, at the agent panel, click on the “Let’s get started” button and sign up or log in with your credentials.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762085091479/abb9f832-b66a-42f5-990c-0a070dc33fd9.png" alt="Kombai agent vs code " class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Now it’s time to test the agent for real work. To do so, I’ll be using the Figma file attached to build this portfolio.</p>
<p>A few things to keep in mind as you get going:</p>
<ul>
<li><p>You’ll need to enable WebGL if Figma is not working on your browser.</p>
</li>
<li><p>You need to know how to copy the Figma file link and how to export the design from Figma.</p>
</li>
</ul>
<p>To copy the Figma design file link, open your Figma design file and simply select your desired design, select copy/paste, and then select copy link to selection. It will copy the complete design file URL.</p>
<p>You can also copy the link of any Figma component and follow the same approach to get the desired outcome.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762935992593/08f6443d-4a62-42fc-8294-0c8f8000bef0.png" alt="figma-design-portfolio" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Open the agent extension in VSCode and select the Figma (icon) agent at the bottom of the agent toolbar. It will open a new pop-up. In it, paste the link you copied to the design file (check the screenshot below). Then you can prompt the agent with what you want it to do with this Figma file.</p>
<p>In my case, I wanted to replicate the same design, so I gave this prompt along with my Figma design link:</p>
<blockquote>
<p>“You are an expert UI/UX designer and your task is to build and replicate the entire Figma design in the HTML/CSS/JS code from the attached URL.“</p>
</blockquote>
<p>After confirming this, the agent will start working to replicate the same design as you’ve seen in the Figma file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761456000444/a34b5abe-cb75-4634-b090-a53d1f4df026.png" alt="figma-to-code-kombai-agent" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>And here are the results:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763136179145/eb51a1ca-7d63-4a16-ba80-80854d715066.png" alt="figma-to-code-kombai-output" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Now you have the full picture of both approaches and when to use each one.</p>
<p>Here is the live Project link - <a target="_blank" href="https://fcc-demo.netlify.app/">FCC FIGMA TO CODE</a></p>
<p>Here is the GitHub link for the project code - <a target="_blank" href="https://github.com/prankurpandeyy/fcc-demo-portfolio">Github Code</a></p>
<h3 id="heading-challenges-in-ai-generated-code-and-why-developer-oversight-is-essential">Challenges in AI-Generated Code (and Why Developer Oversight Is Essential)</h3>
<p>AI tools can speed up the design-to-code process, but the output is rarely production-ready. Most tools struggle with layout precision, accessibility, and responsiveness, especially in real-world designs. You should expect to review and improve various parts of the generated code, such as:</p>
<ul>
<li><p><strong>Spacing and alignment issues:</strong> AI may misinterpret padding, margins, or grid spacing, so layouts often need manual adjustment.</p>
</li>
<li><p><strong>Responsive breakpoints:</strong> Most tools generate layouts for a single screen size. You still need to add tablet/mobile breakpoints and test them across devices.</p>
</li>
<li><p><strong>Semantic HTML:</strong> AI tends to use too many <code>&lt;div&gt;</code> elements instead of meaningful tags like <code>&lt;header&gt;</code>, <code>&lt;nav&gt;</code>, <code>&lt;section&gt;</code>, or <code>&lt;button&gt;</code>.</p>
</li>
<li><p><strong>Accessibility gaps:</strong> Missing alt text, improper labels, weak colour contrast choices, and a lack of ARIA(HTML Tags) attributes are common issues.</p>
</li>
<li><p><strong>Utility class overload (in Tailwind-based code):</strong> AI outputs long, repetitive class lists that need cleanup for maintainability.</p>
</li>
<li><p><strong>Inconsistent component structure:</strong> AI may generate components that aren’t reusable or follow naming conventions, so refactoring is often required.</p>
</li>
<li><p><strong>Tokens and theming:</strong> Colours, font sizes, and spacing may not map to design tokens unless manually corrected.</p>
</li>
</ul>
<p>Because of these limitations, AI-generated code should be treated as a <strong>starting point</strong>, not a final product. You’ll still need to validate the logic, refine the structure, and ensure the final result meets real-world quality standards. AI reduces repetitive work, but you, as the developer, need to ensure the code’s correctness, accessibility, and long-term maintainability.</p>
<h3 id="heading-what-i-prefer">What I Prefer</h3>
<p>The manual method gives you complete control and teaches you the fundamentals, which are essential for understanding how layouts, spacing, and components actually translate into real code.</p>
<p>When you write the HTML, CSS, and component structure yourself, you build a deeper understanding of how layouts, spacing, responsiveness, typography, and accessibility truly work under the hood. These fundamentals are what make you a strong frontend developer, and no automated tool can replace that learning.</p>
<p>AI-assisted design-to-code tools can help with speed – especially in the early stages when you just want a quick starting point. They remove some of the repetitive setup work, but the output almost always needs refinement.</p>
<p>In real projects, the most dependable workflow is a combination of both approaches: Use automation only for the boilerplate, then rely on your own frontend knowledge to clean up, reorganise, and fine-tune the interface so it meets real-world standards.</p>
<p><strong>Personally, I still prefer coding my designs manually because it keeps me connected to the craft and helps me build muscle memory.</strong> It’s the only way to fully understand how the design translates into a live, responsive interface and how each decision affects performance and user experience.</p>
<p>AI tools don’t replace frontend developers. They simply support them. They handle repetitive tasks so you can focus on the skills that truly matter: clarity of structure, accessibility, responsive behaviour, and crafting an experience that feels polished and intentional.</p>
<h2 id="heading-copywriting-for-your-portfolio">Copywriting for Your Portfolio</h2>
<p>Now that your portfolio is designed and coded, let’s turn our attention back to what it actually says.</p>
<p>Copywriting is the art of using words to convince people to take a specific action, like buying a product, signing up for a service, or visiting a website. It’s a mix of creativity and marketing, where words are used to sell ideas or products smartly and emotionally.</p>
<p>A copywriter writes many types of content, from sales pages, website text, and social media posts to ad scripts and emails. The goal is simple: to make people take action.</p>
<p>So what makes copywriting effective?</p>
<ul>
<li><p><strong>Knowing your audience:</strong> A good copywriter understands what people need, what problems they face, and what motivates them.</p>
</li>
<li><p><strong>Using persuasive words:</strong> Words that spark emotions and make readers want to act.</p>
</li>
<li><p><strong>Clarity and impact:</strong> Keeping the message short, clear, and easy to understand.</p>
</li>
<li><p><strong>Consistent brand voice:</strong> Writing in a tone that matches the brand’s personality — whether it’s fun, professional, or inspiring.</p>
</li>
</ul>
<h3 id="heading-how-to-use-copywriting-in-your-portfolio">How to Use Copywriting in Your Portfolio</h3>
<p>Your portfolio isn’t just about showing your work – it’s about telling your story in a way that connects with people. That’s where copywriting comes in. Good copy turns your portfolio from a plain showcase into something that feels personal, clear, and convincing.</p>
<p>Here’s how you can use copywriting effectively while building your portfolio:</p>
<h3 id="heading-1-start-with-a-strong-headline">1. Start With a Strong Headline</h3>
<p>The first line people see should instantly tell them <em>who you are</em> and <em>what you do</em>. For example:</p>
<blockquote>
<p>“I build modern, responsive web apps that turn ideas into digital reality.”</p>
</blockquote>
<p>Your headline is like your elevator pitch: short, powerful, and clear.</p>
<h3 id="heading-2-tell-your-story">2. Tell Your Story</h3>
<p>In the About Me section, don’t just list your skills. You should also tell visitors about your journey. Write about how you got started programming, what you’ve learned along the way, and what drives you. Keep it conversational and real, like you’re talking to a friend.</p>
<blockquote>
<p>“I started coding six years ago with simple HTML pages. Today, I design full-stack apps and help startups bring their ideas to life.”</p>
</blockquote>
<h3 id="heading-3-write-benefit-focused-descriptions">3. Write Benefit-Focused Descriptions</h3>
<p>When you show your projects, don’t just describe <em>what</em> you built. Explain <em>why</em> it matters.</p>
<blockquote>
<p>Instead of: “I built a task manager app.”<br>Try: “A simple, clutter-free task manager that helps users stay productive without distractions.”</p>
</blockquote>
<p>This small change turns your project into a <em>problem-solving story</em>, not just a tech demo.</p>
<h3 id="heading-4-add-a-call-to-action-cta">4. Add a Call-to-Action (CTA)</h3>
<p>Every portfolio should guide visitors toward an action, like contacting you, checking your GitHub, or reading your blog.</p>
<p>Here are some examples:</p>
<blockquote>
<p>“Want to collaborate? Let’s build something amazing together.”<br>“Looking for a developer who writes clean and efficient code? Reach out!”</p>
</blockquote>
<p>A clear CTA shows confidence and gives people a direction.</p>
<h3 id="heading-5-keep-it-simple-and-authentic">5. Keep It Simple and Authentic</h3>
<p>Avoid fancy words or buzzwords. Write like a human, not a brochure. Use simple, clear sentences that sound like your real voice.</p>
<p>Good copywriting is not about being clever – it’s about being <em>clear and honest</em>.</p>
<h3 id="heading-6-maintain-a-consistent-tone">6. Maintain a Consistent Tone</h3>
<p>Whether your style is formal or friendly, keep it the same across all pages – home, about, projects, and contact. A consistent tone helps build your personal brand and makes your portfolio feel professional.</p>
<p>Copywriting is the invisible thread that ties your portfolio together. It helps people not just <em>see</em> your work, but <em>feel</em> your story.</p>
<h2 id="heading-testing-benchmarks-for-a-portfolio-website">Testing Benchmarks for a Portfolio Website</h2>
<p>Before your portfolio goes live, it’s important to test it so that you know it looks and works as it’s supposed to. A fast, responsive, and accessible site leaves a strong first impression, and benchmarks help you measure whether it’s up to your standards. And a well-tested site loads faster, ranks better, and gives users (and recruiters) a seamless experience.</p>
<p>Below are the key benchmarks you should always check, along with why they matter.</p>
<h3 id="heading-1-page-load-time">1. Page Load Time</h3>
<p>This is the time it takes for your page to fully load after someone visits it. A fast-loading site feels smooth and professional, while a slow one instantly turns people away.</p>
<p>This matters because most visitors leave if a site takes more than 3 seconds to load. Tools like <a target="_blank" href="https://gtmetrix.com">GTmetrix</a> or Pingdom can help you track and improve page load speed by optimising images and reducing unnecessary scripts.</p>
<h3 id="heading-2-core-web-vitals-lcp-inp-cls">2. Core Web Vitals (LCP, INP, CLS)</h3>
<p>Google uses <strong>Core Web Vitals</strong> to measure real-world user experience.</p>
<ul>
<li><p><strong>LCP (Largest Contentful Paint):</strong> How quickly your main content becomes visible.</p>
</li>
<li><p><strong>INP (Interaction to Next Paint):</strong> How fast your site responds when users interact.</p>
</li>
<li><p><strong>CLS (Cumulative Layout Shift):</strong> How stable your layout is while loading.</p>
</li>
</ul>
<p>These metrics directly affect how users perceive your site and also impact SEO ranking. You can test them on <a target="_blank" href="https://pagespeed.web.dev">PageSpeed Insights.</a></p>
<h3 id="heading-3-mobile-friendliness">3. Mobile Friendliness</h3>
<p>Most people will view your portfolio on their phones, so it needs to look and work perfectly on smaller screens.</p>
<p>A mobile-optimised site not only improves user experience but also ranks better on Google’s mobile search results. Use responsive layouts and flexible grids to ensure smooth viewing on all devices.</p>
<h3 id="heading-4-accessibility-compliance-wcag">4. Accessibility Compliance (WCAG)</h3>
<p>Accessibility means making your portfolio usable for everyone, including people with disabilities.</p>
<p>This is important because following WCAG standards (like proper colour contrast, keyboard navigation, and alt text for images) shows professionalism and inclusivity. Tools like Lighthouse or WAVE can help you check how your portfolio ranks for key accessibility metrics.</p>
<h3 id="heading-5-seo-best-practices">5. SEO Best Practices</h3>
<p>SEO isn’t just for businesses. It can also help your personal site appear when someone searches your name or skills.</p>
<p>If you add proper meta tags, structured headings (H1, H2, H3), and descriptive URLs, these features can help recruiters or clients find you more easily. A well-optimised portfolio often performs better on job searches and tech blogs.</p>
<h3 id="heading-6-responsiveness-interaction-delay">6. Responsiveness (Interaction Delay)</h3>
<p>Responsiveness measures how quickly your website reacts when users click or scroll. And a laggy interface feels unprofessional and hurts user engagement. By minimising heavy scripts and optimising animations, you ensure smooth, immediate feedback for every action.</p>
<h3 id="heading-7-security-checks-https">7. Security Checks (HTTPS)</h3>
<p>Even a simple portfolio needs <strong>HTTPS</strong>. It builds trust and protects both you and your visitors from data breaches. Browsers like Chrome now flag non-secure sites, so enabling SSL is a must.</p>
<h3 id="heading-8-resource-size-html-css-js-images">8. Resource Size (HTML, CSS, JS, Images)</h3>
<p>Heavy resources can slow everything down. Compressing files, minifying CSS/JS, and using next-gen image formats (like WebP) can dramatically improve speed and performance.</p>
<h3 id="heading-9-browser-and-device-compatibilityhttpspagespeedwebdev">9. Browser and Device Compatibilit<a target="_blank" href="https://pagespeed.web.dev">y</a></h3>
<p>Not everyone uses Chrome on a laptop. So make sure you test your portfolio across major browsers (Chrome, Firefox, Safari, Edge) and devices (desktop, tablet, mobile). Simulated testing tools like DebugBear or Basemark Web help catch layout issues early.</p>
<h3 id="heading-10-real-user-monitoring-rum">10. Real User Monitoring (RUM)</h3>
<p>Instead of just testing in a lab, RUM captures how real visitors experience your site. This helps you understand performance in real-world scenarios – on different devices, networks, and locations – and adjust your design based on real data.</p>
<h2 id="heading-hosting-your-portfolio">Hosting Your Portfolio</h2>
<p>Now it’s time to push your changes to GitHub and deploy them on a hosting provider of your choice. Hosting services play a crucial role in showcasing your work. Depending on the type of projects you build, here are some of the best free hosting options that I have used so far for my personal and professional projects.</p>
<ul>
<li><p><strong>Vercel</strong> – Best for Next.js/React projects, offering seamless deployment inside the Vercel ecosystem.</p>
</li>
<li><p><strong>GitHub Pages</strong> – Great for hosting static websites and personal portfolios.</p>
</li>
<li><p><strong>Netlify</strong> – Ideal for frontend-heavy projects with easy deployment and CI/CD integration.</p>
</li>
</ul>
<p>Your portfolio is ready, and you can share it anywhere with just a link.</p>
<h2 id="heading-how-to-use-your-portfolio-effectively">How to Use Your Portfolio Effectively</h2>
<p>Now that your portfolio is ready, it’s time to use it the right way. Whether you’re applying for a job, pitching to a freelance client, or simply networking with like-minded people, your portfolio is your strongest asset.</p>
<p>Think of it as your digital introduction. It not only shows what you’ve built but also how you think and work. The key is to use it smartly in the right context.</p>
<p>Let’s say you come across a job post or want to reach out directly to a recruiter or a company founder. Instead of just sending a plain résumé, you can make your message stand out by attaching your portfolio link. Here’s an example of how you can do it:</p>
<p>Example email/direct message:</p>
<blockquote>
<p><strong><em>Hi [Hiring Manager/CEO Name],</em></strong></p>
<p><strong><em>I’m Prankur, a Full Stack Developer from India with over 6 years of experience building mobile and web applications.</em></strong></p>
<p><strong><em>I came across the opening for [Job Title/Role] at your company and believe my skills align perfectly with what you’re looking for.</em></strong></p>
<p><strong><em>You can explore my work here: [Portfolio URL]</em></strong></p>
<p><strong><em>I’m available to start immediately and excited about the opportunity to contribute to your team and codebase.</em></strong></p>
<p><strong><em>Best regards,</em></strong></p>
<p><strong><em>Prankur Pandey</em></strong></p>
</blockquote>
<p>This small but professional touch – including your portfolio link in every email, proposal, or LinkedIn message – increases your chances of being noticed. A well-presented portfolio speaks louder than a résumé, and it helps recruiters or clients quickly understand your skills, design sense, and coding depth.</p>
<p>So, don’t just build your portfolio. <strong>Use it actively</strong>. Share it on job boards, LinkedIn posts, your GitHub bio, or even in casual conversations with potential collaborators. Every share is a new opportunity waiting to unfold.</p>
<h2 id="heading-qampa">Q&amp;A</h2>
<p><strong>1. Is building a portfolio really important?</strong><br>Absolutely. Instead of sending out a dozen links to your GitHub, Behance, and LinkedIn, it’s much more effective to combine all your work into one clean, accessible portfolio site. It makes you look organised, professional, and easy to evaluate.</p>
<p><strong>2. Is it worth buying a domain name?</strong><br>Yes, it is, if you’re serious about your career. Having your own domain (like <a target="_blank" href="http://yourname.dev"><em>yourname.dev</em></a> or <a target="_blank" href="http://yourname.com"><em>yourname.com</em></a>) gives a personal and professional touch,</p>
<p>But if you’re still learning or just experimenting, it’s fine to start with a free domain. Once you have solid projects to show, investing in your own domain is totally worth it.</p>
<p><strong>3. Can I use AI or no-code tools to build my portfolio?</strong><br>You can, but if you’re a developer, you should try coding it yourself first. It’s a great way to showcase your creativity and technical control over design and logic. Here’s a <a target="_blank" href="https://www.freecodecamp.org/news/build-a-simple-portfolio-website-with-html-and-css/">simple and straightforward guide</a> to help you get started with that.</p>
<p>Once your design is ready, you can always use AI or no-code tools to speed up the process or automate parts of it. Think of AI as a helper, not a replacement.</p>
<p><strong>4. How can I get AI tools for testing?</strong><br>It’s easy: visit the official websites of the tools you’re interested in and sign up. Most AI tools offer free trials or limited credits that you can use to explore and test their features based on your workflow and needs.</p>
<p><strong>5. I am just starting. What should I use: AI tools or the Manual Method?</strong><br>I strongly recommend using the Manual Method as it will help you to understand your craft well, and you will also build muscle memory about a technology and how it works.</p>
<p><strong>6. Which Platform should I use for hosting?</strong><br>Most of the hosting providers offer a free plan, so you can start with that. Then, when you feel the need to expand your portfolio, switch to a paid plan.</p>
<h2 id="heading-final-notes">Final Notes</h2>
<p>Building a strong portfolio requires time, effort, and attention to detail. But it’s one of the smartest investments you can make in your tech career.</p>
<p>Tools and templates can help speed up the process, but your creativity, skills, and storytelling are what truly make a portfolio stand out. A well-crafted portfolio not only shows what you can build, it reveals how you think and why your work matters.</p>
<p>While you can use design tools, frameworks, or even AI assistance to save time, make sure you understand the basics of design, structure, and usability. The goal isn’t to create something flashy; it’s to produce something clear, professional, and authentic.</p>
<p>Your portfolio is your digital identity, so treat it like your personal brand. Keep refining it as your skills grow and let it evolve alongside your career.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>A portfolio isn’t just a website. It’s your story told through your work. It helps employers, clients, and collaborators understand what you do best and why you stand out.</p>
<p>In this article, I’ve shared everything that helped me build and refine my own portfolio, from understanding design structure and copywriting to testing and optimisation benchmarks. My goal is to help you create a portfolio that not only looks great but also opens real opportunities for you.</p>
<p>In my next tutorial, I’ll explore something new for sure.</p>
<p><strong>Design + Creativity+Development + Execution = The Ultimate Developer Stack 🔥</strong></p>
<p>Keep learning, keep building, and most importantly — keep sharing your work.</p>
<p>If you found this article useful, feel free to let me know. I’m always open to learning, collaboration, and new opportunities.</p>
<p>Now it's your turn: what are you building next? Let me know by sending me a DM!</p>
<ul>
<li><p>Follow me on <strong>𝕏</strong>: <a target="_blank" href="https://x.com/prankurpandeyy">Prankur's</a> <strong>𝕏</strong></p>
</li>
<li><p>Connect with me on LinkedIn: <a target="_blank" href="https://linkedin.com/in/prankurpandeyy">Prankur's LinkedIn</a></p>
</li>
<li><p>Follow me on GitHub: <a target="_blank" href="https://github.com/prankurpandeyy">Prankur’s GitHub</a></p>
</li>
<li><p>View my Portfolio: <a target="_blank" href="https://prankurpandeyy.is-a.dev/">Prankur's Portfolio</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create and Style Tables with Vanilla JavaScript ]]>
                </title>
                <description>
                    <![CDATA[ Tables are one of the most useful ways to display structured data, whether you’re showing a list of users, sales figures, or project reports. In this tutorial, you will learn how to: Build tables using plain HTML Style them using CSS Create and ma... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-and-style-tables-with-vanilla-javascript/</link>
                <guid isPermaLink="false">68f7d9011382e7a69eb7903e</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Md. Fahim Bin Amin ]]>
                </dc:creator>
                <pubDate>Tue, 21 Oct 2025 19:03:29 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761066375438/ad2ff6f1-336c-4d32-89f7-3294a4bfebbd.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Tables are one of the most useful ways to display structured data, whether you’re showing a list of users, sales figures, or project reports.</p>
<p>In this tutorial, you will learn how to:</p>
<ul>
<li><p>Build tables using plain HTML</p>
</li>
<li><p>Style them using CSS</p>
</li>
<li><p>Create and manipulate tables dynamically using <strong>vanilla JavaScript</strong></p>
</li>
</ul>
<p>By the end, you’ll understand not just how to do this, but why it matters. You’ll also learn about separating data from presentation, which is at the heart of modern web development.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-creating-a-simple-table-with-html">Creating a Simple Table with HTML</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-and-styling-borders">Understanding and Styling Borders</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-html-vs-javascript-for-tables">When to Use HTML vs JavaScript for Tables</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-a-table-dynamically-with-javascript">How to Build a Table Dynamically with JavaScript</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-by-step-explanation">Step-by-Step Explanation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-css-classes-for-styling">How to Add CSS Classes for Styling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-turn-it-into-a-reusable-function">How to Turn It Into a Reusable Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-thoughts-amp-conclusion">Final Thoughts &amp; Conclusion</a></p>
</li>
</ol>
<h2 id="heading-creating-a-simple-table-with-html">Creating a Simple Table with HTML</h2>
<p>Before we involve JavaScript, let’s first understand how a standard HTML table works.</p>
<p>A table in HTML is built from a few key tags:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Tag</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>&lt;table&gt;</code></td><td>Defines the main table container</td></tr>
<tr>
<td><code>&lt;thead&gt;</code></td><td>Groups the header rows</td></tr>
<tr>
<td><code>&lt;tbody&gt;</code></td><td>Contains the table’s data rows</td></tr>
<tr>
<td><code>&lt;tr&gt;</code></td><td>Defines a row</td></tr>
<tr>
<td><code>&lt;th&gt;</code></td><td>Defines a header cell (bold and centered by default)</td></tr>
<tr>
<td><code>&lt;td&gt;</code></td><td>Defines a data cell</td></tr>
</tbody>
</table>
</div><p>Here is a minimal example:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">border</span>=<span class="hljs-string">"1"</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>&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>&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">th</span>&gt;</span>Occupation<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">td</span>&gt;</span>Fahim<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>25<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Software Engineer<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><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760798670028/487aa67e-67db-4d78-b37e-6824ea7cb366.png" alt="Output of the code" class="image--center mx-auto" width="426" height="113" loading="lazy"></p>
<p>Let me break down that code snippet properly:</p>
<ul>
<li><p><code>&lt;table&gt;</code> starts the table.</p>
</li>
<li><p><code>&lt;thead&gt;</code> defines the table header section.</p>
</li>
<li><p>Inside <code>&lt;thead&gt;</code>, we have a <code>&lt;tr&gt;</code> (table row), which contains <code>&lt;th&gt;</code> elements (these are column headers).</p>
</li>
<li><p><code>&lt;tbody&gt;</code> holds the actual data. Each <code>&lt;tr&gt;</code> inside it is one record, and each <code>&lt;td&gt;</code> inside that row is a cell.</p>
</li>
</ul>
<p>The <code>border="1"</code> attribute gives a thin outline around the cells. It’s useful for visualization when you’re learning about tables.</p>
<h2 id="heading-understanding-and-styling-borders">Understanding and Styling Borders</h2>
<p>You might have noticed the <code>border</code> attribute in the <code>&lt;table&gt;</code> tag:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">border</span>=<span class="hljs-string">"1"</span>&gt;</span>
</code></pre>
<p>This is a quick way to add visible outlines. You can even make them thicker, like so:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">border</span>=<span class="hljs-string">"5"</span>&gt;</span>
</code></pre>
<p>The above will render thicker borders, like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760798709116/7225688d-1a13-4199-a527-2001df5705c2.png" alt="Output where border=5" class="image--center mx-auto" width="453" height="148" loading="lazy"></p>
<p>But there is a catch as well…</p>
<h3 id="heading-why-using-border-is-not-a-best-practice">Why Using <code>border</code> Is Not a Best Practice</h3>
<p>The <code>border</code> attribute is an old, inline styling technique. Modern web development separates structure (HTML) from presentation (CSS). That means we now use CSS for all visual styling.</p>
<p>Here’s the modern equivalent:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">table</span> {
  <span class="hljs-attribute">border-collapse</span>: collapse; <span class="hljs-comment">/* prevents double borders */</span>
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid <span class="hljs-number">#444</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">#666</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">8px</span>;
  <span class="hljs-attribute">text-align</span>: left;
}
</code></pre>
<h2 id="heading-when-to-use-html-vs-javascript-for-tables">When to Use HTML vs JavaScript for Tables</h2>
<p>You can absolutely create tables entirely in HTML, but only if the data is static.</p>
<p>Use <strong>HTML</strong> only when:</p>
<ul>
<li><p>The data does not change often (like a static price list).</p>
</li>
<li><p>You know the exact number of rows and columns.</p>
</li>
<li><p>You are not fetching data from an external source.</p>
</li>
</ul>
<p>Use <strong>JavaScript</strong> when:</p>
<ul>
<li><p>The data is dynamic (for example, fetched from an API).</p>
</li>
<li><p>You want to update the table based on user input.</p>
</li>
<li><p>You want to sort, filter, or paginate your table interactively.</p>
</li>
</ul>
<p>JavaScript lets you build tables programmatically by defining data in an array or object and letting code handle the rendering.</p>
<h2 id="heading-how-to-build-a-table-dynamically-with-javascript"><strong>How to Build a Table Dynamically with JavaScript</strong></h2>
<p>We will now create a dynamic table using JavaScript. First, I’ll show you the complete code, and then we’ll break it down step-by-step so you can understand exactly what’s happening.</p>
<h3 id="heading-code-example">Code Example:</h3>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>JS Table Example<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"table-container"</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">script</span>&gt;</span><span class="javascript">
  <span class="hljs-comment">// Step 1: Define your data</span>
  <span class="hljs-keyword">const</span> data = [
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Fahim"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">25</span>, <span class="hljs-attr">job</span>: <span class="hljs-string">"Software Engineer"</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"Sara"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">29</span>, <span class="hljs-attr">job</span>: <span class="hljs-string">"Designer"</span> },
    { <span class="hljs-attr">name</span>: <span class="hljs-string">"David"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">31</span>, <span class="hljs-attr">job</span>: <span class="hljs-string">"Manager"</span> }
  ];

  <span class="hljs-comment">// Step 2: Create a table element</span>
  <span class="hljs-keyword">const</span> table = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"table"</span>);
  table.border = <span class="hljs-string">"1"</span>; <span class="hljs-comment">// for visibility only</span>

  <span class="hljs-comment">// Step 3: Add headers</span>
  <span class="hljs-keyword">const</span> headers = [<span class="hljs-string">"Name"</span>, <span class="hljs-string">"Age"</span>, <span class="hljs-string">"Job"</span>];
  <span class="hljs-keyword">const</span> headerRow = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"tr"</span>);

  headers.forEach(<span class="hljs-function"><span class="hljs-params">text</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> th = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"th"</span>);
    th.textContent = text;
    headerRow.appendChild(th);
  });
  table.appendChild(headerRow);

  <span class="hljs-comment">// Step 4: Add data rows</span>
  data.forEach(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> row = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"tr"</span>);
    <span class="hljs-built_in">Object</span>.values(item).forEach(<span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> {
      <span class="hljs-keyword">const</span> cell = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"td"</span>);
      cell.textContent = value;
      row.appendChild(cell);
    });
    table.appendChild(row);
  });

  <span class="hljs-comment">// Step 5: Insert the table into the DOM</span>
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"table-container"</span>).appendChild(table);
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760798906301/10a7abdf-364a-4b9d-9691-17113ef4229a.png" alt="Table Output" class="image--center mx-auto" width="443" height="215" loading="lazy"></p>
<h3 id="heading-step-by-step-explanation">Step-by-Step Explanation</h3>
<h4 id="heading-step-1-define-the-data-separating-data-from-presentation">Step 1: Define the Data – Separating Data from Presentation</h4>
<p>In web development, data and presentation should be kept separate. In this context, data is the content (like names, ages, jobs) and presentation is how that data looks (HTML table layout, colors, and so on).</p>
<p>We define our data as an array of objects:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> data = [
  { <span class="hljs-attr">name</span>: <span class="hljs-string">"Fahim"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">25</span>, <span class="hljs-attr">job</span>: <span class="hljs-string">"Software Engineer"</span> },
  { <span class="hljs-attr">name</span>: <span class="hljs-string">"Sara"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">29</span>, <span class="hljs-attr">job</span>: <span class="hljs-string">"Designer"</span> },
  { <span class="hljs-attr">name</span>: <span class="hljs-string">"David"</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">31</span>, <span class="hljs-attr">job</span>: <span class="hljs-string">"Manager"</span> }
];
</code></pre>
<p>This structure keeps our data flexible. If you later fetch it from an API or database, your table-rendering logic stays the same.</p>
<p>It also mirrors how modern frameworks (like React or Vue) work: your UI simply renders what is in your data.</p>
<h4 id="heading-step-2-create-the-table-element">Step 2: Create the Table Element</h4>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> table = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"table"</span>);
table.border = <span class="hljs-string">"1"</span>;
</code></pre>
<p>Here we are using <code>document.createElement()</code>, a DOM API method that programmatically creates elements. We have not added it to the page yet. It’s just stored in memory.</p>
<p>So why build it in memory first? Well, it’s faster. Appending many elements to the DOM one-by-one causes reflows (browser recalculating layout). Building the structure first and appending once at the end reduces layout recalculations and improves performance.</p>
<h4 id="heading-step-3-add-the-header-row">Step 3: Add the Header Row</h4>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> headers = [<span class="hljs-string">"Name"</span>, <span class="hljs-string">"Age"</span>, <span class="hljs-string">"Job"</span>];
<span class="hljs-keyword">const</span> headerRow = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"tr"</span>);

headers.forEach(<span class="hljs-function"><span class="hljs-params">text</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> th = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"th"</span>);
  th.textContent = text;
  headerRow.appendChild(th);
});
table.appendChild(headerRow);
</code></pre>
<p>Here, we loop through the header labels and dynamically create <code>&lt;th&gt;</code> cells.</p>
<p>We generate headers automatically because if you later load data from a JSON file, you can automatically extract column names using <code>Object.keys(data[0])</code>. This avoids hardcoding and makes your table generation more flexible.</p>
<h4 id="heading-step-4-populate-the-data-rows">Step 4: Populate the Data Rows</h4>
<pre><code class="lang-js">data.forEach(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> row = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"tr"</span>);
  <span class="hljs-built_in">Object</span>.values(item).forEach(<span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> cell = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"td"</span>);
    cell.textContent = value;
    row.appendChild(cell);
  });
  table.appendChild(row);
});
</code></pre>
<p>We loop through every data object, create a <code>&lt;tr&gt;</code> for each, and then fill in <code>&lt;td&gt;</code> cells for each value. <code>textContent</code> ensures we safely insert text (no HTML injection).</p>
<h4 id="heading-step-5-insert-the-table-into-the-dom">Step 5: Insert the Table into the DOM</h4>
<pre><code class="lang-js"><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"table-container"</span>).appendChild(table);
</code></pre>
<p>This is where our table finally appears on the page. We select the empty <code>&lt;div&gt;</code> (our placeholder) and append the built table to it.</p>
<p>JavaScript does not automatically add tables. It only creates them because we told it to. The <code>appendChild()</code> call is what actually adds it to the live DOM.</p>
<h3 id="heading-why-this-approach-is-better">Why This Approach Is Better</h3>
<p>Using JavaScript to generate tables has several benefits:</p>
<ol>
<li><p><strong>Reusability:</strong> You can reuse the same code for any dataset – just change the array.</p>
</li>
<li><p><strong>Separation of concerns:</strong> Data (JS), structure (HTML), and design (CSS) are all handled independently.</p>
</li>
<li><p><strong>Performance:</strong> Building tables in memory before appending avoids costly DOM reflows.</p>
</li>
<li><p><strong>Interactivity:</strong> You can easily add features like sorting, filtering, or highlighting rows.</p>
</li>
<li><p><strong>Dynamic data:</strong> It is the natural approach when fetching JSON data from APIs.</p>
</li>
</ol>
<h2 id="heading-how-to-add-css-classes-for-styling">How to Add CSS Classes for Styling</h2>
<p>Instead of inline styling, we’ll use classes for better organization:</p>
<pre><code class="lang-js">table.classList.add(<span class="hljs-string">"data-table"</span>);
</code></pre>
<p>Then we’ll define our styles in CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.data-table</span> {
  <span class="hljs-attribute">border-collapse</span>: collapse;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid <span class="hljs-number">#333</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.data-table</span> <span class="hljs-selector-tag">th</span>, <span class="hljs-selector-class">.data-table</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">#888</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
}
</code></pre>
<p>When we say “use them,” we are referring to CSS class names – reusable identifiers that let you style your elements separately from your JavaScript logic.</p>
<h2 id="heading-how-to-turn-it-into-a-reusable-function">How to Turn It Into a Reusable Function</h2>
<p>Finally, let’s make this process reusable. We can wrap everything in a function that generates any table given some data and headers.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createTable</span>(<span class="hljs-params">data, headers, containerId</span>) </span>{
  <span class="hljs-keyword">const</span> table = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"table"</span>);

  <span class="hljs-keyword">const</span> headerRow = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"tr"</span>);
  headers.forEach(<span class="hljs-function"><span class="hljs-params">text</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> th = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"th"</span>);
    th.textContent = text;
    headerRow.appendChild(th);
  });
  table.appendChild(headerRow);

  data.forEach(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> row = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"tr"</span>);
    <span class="hljs-built_in">Object</span>.values(item).forEach(<span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> {
      <span class="hljs-keyword">const</span> td = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"td"</span>);
      td.textContent = value;
      row.appendChild(td);
    });
    table.appendChild(row);
  });

  <span class="hljs-built_in">document</span>.getElementById(containerId).appendChild(table);
}
</code></pre>
<p>Then use it like this:</p>
<pre><code class="lang-js">createTable(data, [<span class="hljs-string">"Name"</span>, <span class="hljs-string">"Age"</span>, <span class="hljs-string">"Job"</span>], <span class="hljs-string">"table-container"</span>);
</code></pre>
<h3 id="heading-when-and-why-to-use-a-function">When and Why to Use a Function</h3>
<p>This pattern is ideal when you need to generate multiple tables on one page, you want cleaner, modular, and testable code, or you plan to integrate with dynamic data sources (like APIs).</p>
<h2 id="heading-final-thoughts-amp-conclusion">Final Thoughts &amp; Conclusion</h2>
<p>We have covered a lot! In this article, so let’s recap what you learned:</p>
<ul>
<li><p>How to create a table with HTML</p>
</li>
<li><p>How to style it properly using CSS</p>
</li>
<li><p>When to use HTML vs JavaScript</p>
</li>
<li><p>How to separate data from presentation</p>
</li>
<li><p>How to generate tables dynamically with JavaScript</p>
</li>
<li><p>How to make your code reusable and efficient</p>
</li>
</ul>
<p>With these foundations, you can now build tables that are dynamic, styled, and data-driven – using nothing but vanilla JavaScript.</p>
<p>Thank you for reading the entire article. I hope you have gained some insight into how to make a subtle transition from typical HTML tables to dynamic JavaScript-based tables. To get more content like this, you can follow me on <a target="_blank" href="https://www.linkedin.com/in/fahimfba/">LinkedIn</a> and <a target="_blank" href="https://x.com/Fahim_FBA">X</a>. You can also check <a target="_blank" href="https://www.fahimbinamin.com/">my website</a> and follow me on <a target="_blank" href="https://github.com/FahimFBA">GitHub</a> if you are into open source and development.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use the react-mui-sidebar Package to Build Responsive, Customizable Sidebars ]]>
                </title>
                <description>
                    <![CDATA[ In modern web development, a well-designed sidebar can greatly improve the user experience by providing easy navigation and access to important features. The react-mui-sidebar, powered by Material-UI, is a helpful React NPM package designed to make i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-react-mui-sidebar-to-build-responsive-customizable-sidebars/</link>
                <guid isPermaLink="false">68e841313a3a459fe2b24ab2</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ npm ]]>
                    </category>
                
                    <category>
                        <![CDATA[ material ui ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Hitesh Chauhan ]]>
                </dc:creator>
                <pubDate>Thu, 09 Oct 2025 23:11:45 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1760051493063/cc42647f-21e7-48f6-873f-b17db780a24a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In modern web development, a well-designed sidebar can greatly improve the user experience by providing easy navigation and access to important features.</p>
<p>The <a target="_blank" href="https://www.npmjs.com/package/react-mui-sidebar">react-mui-sidebar</a>, powered by <a target="_blank" href="https://mui.com/">Material-UI</a>, is a helpful React NPM package designed to make it easier to build responsive and highly customizable sidebars.</p>
<p>In this article, we will explore the key aspects of react-mui-sidebar and how you can use it to elevate the sidebar experience in your React applications.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-mui-material-ui">What is MUI (Material-UI)?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-choose-react-mui-sidebar">Why Choose react-mui-sidebar?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-get-started-with-react-mui-sidebar">How to Get Started with react-mui-sidebar</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before diving into the tutorial, make sure you have the following:</p>
<ul>
<li><p><strong>Basics of React</strong> like components, props, state, and JSX</p>
</li>
<li><p><strong>Familiarity with React Router or Next.js App Router</strong> so you know how linking/navigation works</p>
</li>
<li><p><strong>Understanding of Material-UI / MUI</strong>: theming, components, styling</p>
</li>
<li><p><strong>NPM / Yarn package usage</strong>: installing, importing, and managing dependencies</p>
</li>
<li><p><strong>Basic CSS / layout skills</strong>: Flexbox, widths, responsive design, and so on</p>
</li>
</ul>
<p>Here’s what we’ll be building:</p>
<p><a target="_blank" href="https://www.npmjs.com/package/react-mui-sidebar"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756104211843/d56fb298-d190-4d14-9923-e7ec0827a662.jpeg" alt="d56fb298-d190-4d14-9923-e7ec0827a662" class="image--center mx-auto" width="1051" height="867" loading="lazy"></a></p>
<p>Here’s a <a target="_blank" href="https://react-mui-sidebar.vercel.app/">live demo</a> you can check out, too.</p>
<h2 id="heading-what-is-mui-material-ui"><strong>What is MUI (Material-UI)?</strong></h2>
<p>Material-UI is a widely adopted React UI framework that brings Google's Material Design principles to React applications. React MUI Sidebar leverages the strengths of Material-UI, providing a seamless integration for creating visually appealing and responsive sidebars.</p>
<h3 id="heading-features-of-react-mui-sidebar"><strong>Features of React MUI Sidebar</strong></h3>
<ol>
<li><p><strong>Responsive design:</strong> React MUI Sidebar ensures a consistent and adaptive layout across various screen sizes, catering to the increasing demand for mobile-friendly interfaces.</p>
</li>
<li><p><strong>Customization options:</strong> You can easily change the appearance of the sidebar to match the overall design of you application, allowing for a cohesive and branded look.</p>
</li>
<li><p><strong>Integration with React and Next.js:</strong> React MUI Sidebar seamlessly integrates with both React and Next.js, offering a familiar and efficient development experience.</p>
</li>
<li><p><strong>User-friendly:</strong> React MUI Sidebar is designed with simplicity in mind, making it easy to incorporate into your projects. With intuitive documentation, you can quickly grasp and implement the sidebar functionality.</p>
</li>
<li><p><strong>Icons support:</strong> The sidebar comes with built-in support for icons, helping you enhance the visual appeal and usability of your applications. You can use any icon library and provide the icon component.</p>
</li>
<li><p><strong>Menu and submenu support:</strong> It provides a hierarchical structure with support for both main menus and nested submenus. This feature enables you to organize and present complex navigation structures in a clear and intuitive manner.</p>
</li>
<li><p><strong>Smooth transitions:</strong> The sidebar incorporates smooth transition effects, enhancing the overall user experience by providing a visually pleasing navigation flow. Animations are thoughtfully implemented to avoid any jarring effects during sidebar interactions.</p>
</li>
</ol>
<h2 id="heading-why-choose-react-mui-sidebar"><strong>Why Choose react-mui-sidebar?</strong></h2>
<p>There are various reasons to use this helpful tool. Here are a few big ones:</p>
<h3 id="heading-optimized-performance"><strong>Optimized Performance</strong></h3>
<p>react-mui-sidebar is designed and configured for high performance, ensuring smooth and responsive user interactions. Internally, it minimizes re-renders via memoization so that only parts of the menu that actually change are updated. It uses lightweight DOM structure and conditional rendering of nested items to avoid unnecessary mounting.</p>
<p>Since it's built on MUI, it also leverages efficient styling via the <code>sx</code> prop or styled components rather than heavy theme recalculations.</p>
<p>These features are crucial for applications, especially those with complex or intricate user interfaces, where performance issues can negatively impact the user experience.</p>
<h3 id="heading-community-strength"><strong>Community Strength</strong></h3>
<p>React MUI Sidebar benefits from a large and active user base thanks in part to the large and active Material UI community. This is helpful for users because it means there's a wealth of resources, tutorials, and assistance available.</p>
<p>A strong community can contribute to the growth of the framework, provide solutions to common issues, and foster collaboration among developers.</p>
<h3 id="heading-reliable-maintenance"><strong>Reliable Maintenance</strong></h3>
<p>react-mui-sidebar is actively supported by consistent updates and proactive maintenance from its community. Regular updates often include bug fixes, security patches, and new features, which help make sure that the framework remains current and adaptable to users’ evolving needs. This is especially important for long-term projects, and shows a commitment to the ongoing improvement and support of the framework.</p>
<h2 id="heading-how-to-get-started-with-react-mui-sidebar"><strong>How to Get Started with react-mui-sidebar</strong></h2>
<p>In this tutorial, I’ll walk you through installing and setting up react-mui-sidebar in a React and Next.js application. You’ll learn how to integrate the sidebar, add a logo, create menus, and use links.</p>
<h3 id="heading-step-1-install-react-mui-sidebar">Step 1: Install react-mui-sidebar</h3>
<p>To begin, you’ll need to install the <a target="_blank" href="https://www.npmjs.com/package/react-mui-sidebar">react-mui-sidebar package</a> into your React and Next.js project. You can do this using either npm or yarn.</p>
<h4 id="heading-using-npm">Using npm:</h4>
<pre><code class="lang-javascript">npm install react-mui-sidebar
</code></pre>
<h4 id="heading-using-yarn">Using yarn:</h4>
<pre><code class="lang-javascript">yarn add react-mui-sidebar
</code></pre>
<p>This will add react-mui-sidebar and its dependencies to your project.</p>
<h3 id="heading-step-2-import-the-react-mui-sidebar-component">Step 2: Import the React MUI Sidebar Component</h3>
<p>Once the package is installed, you can import the necessary components from react-mui-sidebar into your project. These components will allow you to customize the sidebar with menus, submenus, and even a logo.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Sidebar, Menu, MenuItem, Submenu, Logo } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-mui-sidebar"</span>;
</code></pre>
<h3 id="heading-step-3-set-up-routing-for-react-app-or-nextjs-app">Step 3: Set Up Routing for React App or Next.js App</h3>
<p>To enable navigation inside react-mui-sidebar components like MenuItem or Logo, you need to pass a link component from either react-router or next/link using the component prop inside the corresponding component like what’s shown in the below example:</p>
<p>If you're using <strong>React Router:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Sidebar</span> <span class="hljs-attr">width</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">270px</span>"}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Logo</span>
        <span class="hljs-attr">component</span>=<span class="hljs-string">{Link}</span>  // <span class="hljs-attr">Passing</span> <span class="hljs-attr">link</span> <span class="hljs-attr">to</span> <span class="hljs-attr">component</span> <span class="hljs-attr">for</span> <span class="hljs-attr">routing</span>
        <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>
        <span class="hljs-attr">img</span>=<span class="hljs-string">"https://adminmart.com/wp-content/uploads/2024/03/logo-admin-mart-news.png"</span>
      &gt;</span>
        AdminMart
      <span class="hljs-tag">&lt;/<span class="hljs-name">Logo</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Menu</span> <span class="hljs-attr">subHeading</span>=<span class="hljs-string">"HOME"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span>
          <span class="hljs-attr">icon</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">CottageOutlinedIcon</span> /&gt;</span>}
          component={Link} // Passing link to component for routing
          link="/tes"
          badge={true}
          isSelected={true}
        &gt;
          {" "}
          {/* text for your link */}
          Link Text
        <span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Menu</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Sidebar</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>If you're using <strong>Next.js App Router:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">"next/link"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Sidebar</span> <span class="hljs-attr">width</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">270px</span>"}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Logo</span>
        <span class="hljs-attr">component</span>=<span class="hljs-string">{Link}</span>  // <span class="hljs-attr">Passing</span> <span class="hljs-attr">link</span> <span class="hljs-attr">to</span> <span class="hljs-attr">component</span> <span class="hljs-attr">for</span> <span class="hljs-attr">routing</span>
        <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>
        <span class="hljs-attr">img</span>=<span class="hljs-string">"https://adminmart.com/wp-content/uploads/2024/03/logo-admin-mart-news.png"</span>
      &gt;</span>
        AdminMart
      <span class="hljs-tag">&lt;/<span class="hljs-name">Logo</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Menu</span> <span class="hljs-attr">subHeading</span>=<span class="hljs-string">"HOME"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span>
          <span class="hljs-attr">icon</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">CottageOutlinedIcon</span> /&gt;</span>}
          component={Link} // Passing link to component for routing
          link="/tes"
          badge={true}
          isSelected={true}
        &gt;
          {" "}
          {/* text for your link */}
          Link Text
        <span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Menu</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Sidebar</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h3 id="heading-step-4-initialize-the-sidebar">Step 4: Initialize the Sidebar</h3>
<p>Now we’ll set up the Sidebar component in your application. You can set the width of the sidebar using the width prop. Here’s a simple example:</p>
<pre><code class="lang-javascript">&lt;Sidebar width={<span class="hljs-string">"270px"</span>}&gt; <span class="hljs-comment">// pass the width you want your sidebar to have</span>
  {<span class="hljs-comment">/* Sidebar Content Goes Here */</span>}
&lt;/Sidebar&gt;
</code></pre>
<p>This initializes the sidebar with a width of 270px. You can adjust this width based on your design requirements.</p>
<h3 id="heading-step-5-add-a-logo-to-the-sidebar">Step 5: Add a Logo to the Sidebar</h3>
<p>You can add a logo inside the sidebar by using the Logo component. To do so, you can provide an src URL or use the img prop to link to a CDN logo image. You can also make the logo clickable by passing a navigation link using the component and href props. Here’s how to do this:</p>
<pre><code class="lang-javascript">&lt;Sidebar width={<span class="hljs-string">"270px"</span>}&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Logo</span> 
    <span class="hljs-attr">component</span>=<span class="hljs-string">{Link}</span> 
    <span class="hljs-attr">href</span>=<span class="hljs-string">”/”</span>
    <span class="hljs-attr">img</span>=<span class="hljs-string">"https://adminmart.com/wp-content/uploads/2024/03/logo-admin-mart-news.png"</span> // <span class="hljs-attr">path</span> <span class="hljs-attr">for</span> <span class="hljs-attr">image</span> <span class="hljs-attr">you</span> <span class="hljs-attr">want</span> <span class="hljs-attr">to</span> <span class="hljs-attr">use</span> <span class="hljs-attr">as</span> <span class="hljs-attr">your</span> <span class="hljs-attr">logo</span>
  &gt;</span>
    AdminMart
  <span class="hljs-tag">&lt;/<span class="hljs-name">Logo</span>&gt;</span></span>
&lt;/Sidebar&gt;
</code></pre>
<p>In this example, we’ve added a logo from a CDN using the img prop, used the component prop to pass the Link, and set the navigation path to (/) (the homepage) using the href prop. We’ve also set the text “AdminMart” as the name of the application.</p>
<h3 id="heading-step-6-create-a-menu-inside-the-sidebar">Step 6: Create a Menu Inside the Sidebar</h3>
<p>Now let’s create a menu inside the sidebar using the Menu component. You can specify a submenu heading using the subHeading prop. Inside the Menu, you can add MenuItem components for each item.</p>
<p>You can also provide a link prop along with the component prop to the MenuItem to turn the item into a clickable link.</p>
<p>Here’s how you can structure the menu:</p>
<pre><code class="lang-javascript">&lt;Sidebar width={<span class="hljs-string">"270px"</span>}&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Menu</span> <span class="hljs-attr">subHeading</span>=<span class="hljs-string">"HOME"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Link}</span>  <span class="hljs-attr">link</span>=<span class="hljs-string">"/"</span>  <span class="hljs-attr">badge</span>=<span class="hljs-string">”true”</span>  <span class="hljs-attr">isSelected</span>=<span class="hljs-string">{true}</span> &gt;</span>
      Modern
    <span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span>&gt;</span>eCommerce<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span>&gt;</span>Analytical<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">Menu</span>&gt;</span></span>
&lt;/Sidebar&gt;
</code></pre>
<p>In this example:</p>
<ul>
<li><p>We’ve added a Menu with the heading “HOME”.</p>
</li>
<li><p>The first MenuItem has a link prop, so clicking it will navigate to the homepage (/).</p>
</li>
<li><p>The second and third MenuItem components are simple text items without links.</p>
</li>
</ul>
<p>The <code>badge="true"</code> prop can be used to indicate a badge or notification on the MenuItem, and the <code>isSelected={true}</code> prop marks this menu item as currently selected or active. You can customize this feature according to your needs.</p>
<h3 id="heading-step-7-add-submenus-optional">Step 7: Add Submenus (Optional)</h3>
<p>To add submenus inside the main menu, you can use the Submenu component. The Submenu can be nested inside the Menu component and contains its own set of MenuItems. Use the title prop to set the submenu heading</p>
<p>Here’s an example of adding a submenu:</p>
<pre><code class="lang-javascript">&lt;Sidebar width={<span class="hljs-string">"270px"</span>}&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Menu</span> <span class="hljs-attr">subHeading</span>=<span class="hljs-string">"SERVICES"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span>  <span class="hljs-attr">component</span>=<span class="hljs-string">{Link}</span>   <span class="hljs-attr">link</span>=<span class="hljs-string">"/web-development"</span>&gt;</span>Web Development<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span>   <span class="hljs-attr">component</span>=<span class="hljs-string">{Link}</span>  <span class="hljs-attr">link</span>=<span class="hljs-string">"/seo-services"</span>&gt;</span>SEO Services<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Submenu</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Marketing"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span>  <span class="hljs-attr">component</span>=<span class="hljs-string">{Link}</span>  <span class="hljs-attr">link</span>=<span class="hljs-string">"/digital-marketing"</span>&gt;</span>Digital Marketing<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span>  <span class="hljs-attr">component</span>=<span class="hljs-string">{Link}</span>  <span class="hljs-attr">link</span>=<span class="hljs-string">"/content-marketing"</span>&gt;</span>Content Marketing<span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Submenu</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">Menu</span>&gt;</span></span>
&lt;/Sidebar&gt;
</code></pre>
<p>In this example:</p>
<ul>
<li><p>A submenu under the "Marketing" heading is added inside the "SERVICES" menu.</p>
</li>
<li><p>The submenu contains two MenuItems with links to different service pages.</p>
</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>You have now successfully integrated a fully functional sidebar in your React and Next.js application using react-mui-sidebar. You can further customize the sidebar by:</p>
<ul>
<li><p>Modifying the width and design.</p>
</li>
<li><p>Adding more submenus, menu items, or icons.</p>
</li>
<li><p>Using links to navigate between pages.</p>
</li>
</ul>
<p>This setup provides a flexible, responsive, and easy-to-use sidebar, which is perfect for most web applications.</p>
<h3 id="heading-try-it-out">Try It Out:</h3>
<p>You can view the working demo of the react-mui-sidebar here: <a target="_blank" href="https://react-mui-sidebar.vercel.app/"><strong>View Demo</strong></a><strong>.</strong></p>
<p><strong>Note:</strong> in this tutorial, we utilized <a target="_blank" href="https://mui.com/material-ui/material-icons/">Material UI Icons</a> to construct this sidebar. Feel free to choose an alternative library or use different icons based on your specific requirements.</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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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="600" height="400" 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 to Use the CSS text-wrap Property to Create Balanced Text Layouts on Your Websites ]]>
                </title>
                <description>
                    <![CDATA[ An inconsistent text layout can really ruin the look of your website’s design. Maybe a heading has an extra word that wraps to another line, or in a paragraph some lines are longer than others. This can leave the whole thing looking messy and hard to... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-css-text-wrap-property/</link>
                <guid isPermaLink="false">67fd1442fd23722b0a451053</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Responsive Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Azubuike Duru ]]>
                </dc:creator>
                <pubDate>Mon, 14 Apr 2025 13:57:22 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744638131989/38357168-abda-4f7b-8c4f-568f64b586df.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>An inconsistent text layout can really ruin the look of your website’s design. Maybe a heading has an extra word that wraps to another line, or in a paragraph some lines are longer than others. This can leave the whole thing looking messy and hard to read.</p>
<p>Before now, developers used tags like <code>&lt;br&gt;</code> or <code>&lt;span&gt;</code> to manually adjust word spacing. But what happens in cases where you also need to consider the responsiveness of the website? Well, the new <code>text-wrap: balance</code> property in CSS can now automatically calculate and divide the lines in such a way that every word looks organized and even. Like this:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_4C8BE890CB3AB8AD50C286E15DBA884FF164212E142B1E75C767C0221DB183E7_1743742346617_Desktop+-+1-3.png" alt="Heading before and after applying 'text-wrap: balance' for improved wrapping." width="1440" height="411" loading="lazy"></p>
<p>In this article, you’ll learn how the <code>text-wrap</code> property works and how to use it in your code. You’ll also see a few examples along the way.</p>
<p>Without wasting time, let's get right into it.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-understanding-the-problems">Understanding the Problems</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-introducing-text-wrap">Introducing text-wrap</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-text-wrap">What is text-wrap?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-basic-syntax-of-text-wrap">Basic Syntax of text-wrap</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-text-wrap-vs-max-width-when-to-use-each">text-wrap vs. max-width : When to Use Each</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-when-to-use-max-width-vs-text-wrap">When to Use max-width vs text-wrap</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-browser-support-and-considerations">Browser Support and Considerations</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-practical-implementation-step-by-step-guide">Practical Implementation: Step-by-Step Guide</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-understanding-the-problems">Understanding the Problems</h2>
<p>Apart from making words harder to read when your text is unevenly displayed, there are other issues uneven or poorly displayed text can cause on your website as a whole. Some of these are:</p>
<ul>
<li><p><strong>Responsive Design</strong>: We wouldn't have any issues if we could manually design for every screen size and carefully place and space the lines of our text exactly as we wanted users to read them. Unfortunately, we can't do this, which is why making designs responsive is always crucial. When text adjusts from one screen size to another, lines break, and what looks good on a desktop may look terrible on a tablet view.</p>
</li>
<li><p><strong>Headings and Short Paragraphs</strong>: Since paragraphs and small blocks of text have many words, there is a high probability of words ending in a very unbalanced way. Often, we see a heading line ending with just one word, forming an awkward shape in the overall design.</p>
</li>
<li><p><strong>Dynamic Content</strong>: If your website contains dynamic content (such as cards of various sizes, product descriptions, or blog posts), having no <code>text-wrap</code> might make your layout break or appear unpredictable.</p>
</li>
</ul>
<h2 id="heading-introducing-text-wrap">Introducing <code>text-wrap</code></h2>
<p>In the last section, we looked at the problems attributed to uneven text distribution. In this section, you’ll see how <code>text-wrap</code> is a game changer in how you organize your text.</p>
<p>Before <code>text-wrap</code>, developers relied heavily on <code>max-width</code>, <code>text-align</code>, or <code>&lt;br&gt;</code> to control text lines. The new <code>text-wrap</code> CSS property was created to help break text naturally across lines without making it look out of place, preventing the need for trial and error in checking if text fits.</p>
<h3 id="heading-what-is-text-wrap">What is <code>text-wrap</code>?</h3>
<p><code>text-wrap</code> is a CSS property that can help you adjust and space text automatically, break lines evenly without using the rigid <code>&lt;br&gt;</code> tag, and not have to rely on <code>text-align</code>, which didn't work on all screen sizes.</p>
<p>With <code>text-wrap</code>, your headings and paragraphs are sure to look good. Instead of having some lines that look longer than others, <code>text-wrap</code> neatly arranges everything to appear visually appealing.</p>
<h3 id="heading-basic-syntax-of-text-wrap">Basic Syntax of <code>text-wrap</code></h3>
<p>There are two major ways to apply text-wrap to your text. These values are:</p>
<p><code>text-wrap: balance</code><strong>: (The Smart Heading Balancer)</strong></p>
<p>This is the smart way of telling the browser to adjust the text evenly, regardless of the screen size.</p>
<p>Code snippet:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">text-wrap</span>: balance;
}
</code></pre>
<p>In this code, the heading text lines will split naturally without any weird short lines.</p>
<p><code>text-wrap: pretty;</code> <strong>(The Smart Paragraph Balancer)</strong></p>
<p>Just as <code>text-wrap: balance</code> works best for headings, <code>text-wrap: pretty</code> is the best for styling long paragraphs.</p>
<p>Code snippet:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">p</span>{
  <span class="hljs-attribute">text-wrap</span>: pretty;
}
</code></pre>
<p>The <code>p</code> in this code will make sure the paragraphs maintain natural readability.</p>
<p><strong>Other values include:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Value</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>wrap</code></td><td>Default state</td></tr>
<tr>
<td><code>nowrap</code></td><td>Prevents text from wrapping to the next line</td></tr>
<tr>
<td><code>stable</code></td><td>Ensures things are kept in place until the content changes itself</td></tr>
</tbody>
</table>
</div><h2 id="heading-text-wrap-vs-max-width-when-to-use-each"><code>text-wrap</code> vs. <code>max-width</code> : When to Use Each</h2>
<p><code>max-width</code> was always the go-to option for developers in the past. While this method works in most cases, it won’t stop uneven text distribution. Let's compare it with the new <code>text-wrap</code> CSS property so you can know when to use each one.</p>
<p><strong>Using</strong> <code>max-width</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">400px</span>;
}
</code></pre>
<p>The <code>max-width</code> here forces the heading not to exceed a 400px width. This can be good for controlling short body paragraphs but can cause unevenness for headings when dealing with multiple screen sizes.</p>
<p><strong>Using</strong> <code>text-wrap</code>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">text-wrap</span>: balance;
}
</code></pre>
<p>Here, the browser dynamically breaks the heading text in a balanced way, preventing any weird-looking single lines.</p>
<h3 id="heading-when-to-use-max-width-vs-text-wrap">When to Use <code>max-width</code> vs <code>text-wrap</code></h3>
<p>Use <code>text-wrap: balance</code> when you want a more natural text read without any weird line breaks.</p>
<p>Use <code>max-width</code> when you need to control the text width and don't necessarily care how the lines break.</p>
<p>Use both if you want a more natural read within a confined width limit.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">500px</span>;
  <span class="hljs-attribute">text-wrap</span>: balance;
}
</code></pre>
<p>This ensures the heading stays within a 500px limit while maintaining an even text distribution.</p>
<h3 id="heading-browser-support-and-considerations">Browser Support and Considerations</h3>
<p>Currently, Chrome and Edge are the only main browsers that support the new <code>text-wrap</code> property. If you are building a project that should work on browsers like Safari and Firefox, you will need to use traditional text formatting methods like <code>text-align</code>, <code>&lt;br&gt;</code>, or <code>max-width</code> instead.</p>
<p>Fallback snippet:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">text-wrap:</span> balance) {
  <span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">text-wrap</span>: balance;
  }
}
</code></pre>
<p>The <code>@support</code> is a pro tip to apply this style to only supported browsers.</p>
<h2 id="heading-practical-implementation-step-by-step-guide">Practical Implementation: Step-by-Step Guide</h2>
<p>Now that you’ve seen how important <code>text-wrap</code> can be and how to use it, let’s put that knowledge into practise and see real examples, compare the before and after screens of using it (and not), and check how it reacts in responsive designs as well.</p>
<h3 id="heading-1-applying-text-wrap-balance-to-headings">1. Applying <code>text-wrap: balance</code> to Headings</h3>
<p>In this section, we will see how the heading lines in the topic <strong>"How to Use CSS Text Balance: A Simple Trick for Smoother, Cleaner Designs"</strong> will break across different sizes and how it looks when <code>text-wrap: balance</code> is applied.</p>
<p><strong>Without</strong> <code>text-wrap: balance</code>:</p>
<p>HTML</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title"</span>&gt;</span>How to Use CSS Text Balance: A Simple Trick for Smoother, Cleaner Designs<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
</code></pre>
<p>CSS</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.title</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2.5rem</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
}
</code></pre>
<p>Without any special application to the headings, it will just adjust freely.</p>
<p>Result:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_4C8BE890CB3AB8AD50C286E15DBA884FF164212E142B1E75C767C0221DB183E7_1743740541468_Screenshot+2025-04-04+at+5.21.36AM+1.png" alt="Heading without 'text-wrap: balance', showing uneven wrapping." width="3360" height="1325" loading="lazy"></p>
<p><strong>With</strong> <code>text-wrap: balance</code>:</p>
<p>CSS</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.title</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2.5rem</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">text-wrap</span>: balance;
}
</code></pre>
<p>Now, the browser automatically adjusts the line breaks to ensure a more even distribution.</p>
<p>Result:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_4C8BE890CB3AB8AD50C286E15DBA884FF164212E142B1E75C767C0221DB183E7_1743740708025_Screenshot+2025-04-04+at+5.24.26AM.png" alt="Heading with 'text-wrap: balance', showing smart readable behavior and wrapping" width="3360" height="1395" loading="lazy"></p>
<h3 id="heading-2-using-text-wrap-pretty-on-short-paragraphs">2. Using <code>text-wrap: pretty</code> on Short Paragraphs</h3>
<p>You’ve now seen how <code>text-wrap: balance</code> handles headings, so lets also take a look at how it breaks the lines evenly in your text paragraphs. As I mentioned above, the value <code>pretty</code> is mostly used for paragraphs or short block of words. Here’s how it works and appears on a block of text.</p>
<p><strong>Without</strong> <code>text-wrap: pretty</code>:</p>
<p>HTML</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">"subText"</span>&gt;</span> Do you know that inconsistent text layout can ruin the look of your website design? Maybe a heading has an extra word that takes up another line or in a paragraph some lines are longer than others whereby leaving the whole thing looking messed up and hard to read.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>CSS</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.subText</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2rem</span>;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>;
}
</code></pre>
<p>In this code, text adjustment will behave normally without any smart contraints.</p>
<p>Result:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_4C8BE890CB3AB8AD50C286E15DBA884FF164212E142B1E75C767C0221DB183E7_1743739991569_Screenshot+2025-04-04+at+5.11.08AM.png" alt="Paragraph without 'text-wrap: pretty', showing uneven wrapping." width="3360" height="1231" loading="lazy"></p>
<p><strong>With</strong> <code>text-wrap: pretty</code>:</p>
<p>CSS</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.subText</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2rem</span>;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.5</span>;
  <span class="hljs-attribute">text-wrap</span>: pretty;
}
</code></pre>
<p>The code above makes the line breaks evenly in a way that it will be easier for someone to read through.</p>
<p>Result:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_4C8BE890CB3AB8AD50C286E15DBA884FF164212E142B1E75C767C0221DB183E7_1743739834917_Screenshot+2025-04-04+at+5.09.49AM.png" alt="Paragraph with 'text-wrap: pretty', showing smart readable behavior and wrapping" width="3360" height="1353" loading="lazy"></p>
<h3 id="heading-how-text-wrap-works-in-responsive-design">How <code>text-wrap</code> Works in Responsive Design</h3>
<p>When you use <code>text-wrap</code> on your text, you need not to worry how it is going to appear on various screen sizes. The below video shows you what I mean by that:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_4C8BE890CB3AB8AD50C286E15DBA884FF164212E142B1E75C767C0221DB183E7_1743738297774_ScreenRecording2025-04-04at4.37.18AM-ezgif.com-video-to-gif-converter.gif" alt="A gif showing how 'text-wrap' smoothly adjusts on a responsive screen " width="800" height="450" loading="lazy"></p>
<h3 id="heading-using-media-queries-for-extra-control">Using Media Queries for Extra Control</h3>
<p>Combine <code>media-queries</code> and <code>text-wrap</code> to have a great special kind of control on how your text appears on various screens.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2.5rem</span>;
  <span class="hljs-attribute">text-wrap</span>: balance;
}

<span class="hljs-comment">/* On smaller screens, reduce font size and apply text-balancing */</span>
<span class="hljs-keyword">@media</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">600px</span>) {
  <span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
    <span class="hljs-attribute">text-wrap</span>: balance;
  }
}
</code></pre>
<p>This code ensures your heading text adapts and remains clean across multiple device sizes.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>How text displays is something every good developer should pay attention to. It plays a big role in user experience. By using <code>text-wrap</code>, you can ensure that your website layouts don't look messy or difficult to read.</p>
<p>One of the best things about using <code>text-wrap</code> in your text formatting is that it just works every time. You don’t need to bother with <code>&lt;br&gt;</code> tags, tweak <code>max-width</code>, or fight with text alignment.</p>
<p>Even though it's not yet supported by all browsers, adding it to your next project will future-proof your design so it’s always intact and good-looking.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Everything You Need to Know About Web Accessibility ]]>
                </title>
                <description>
                    <![CDATA[ The web is a great place to access information and connect with people. It has opened up countless opportunities, making life more convenient in many ways. But not everyone experiences the web in the same way. Websites are difficult to use for people... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-web-accessibility-handbook/</link>
                <guid isPermaLink="false">67d9aa58a50edbbdc70e2941</guid>
                
                    <category>
                        <![CDATA[ Accessibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ a11y ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kunal Nalawade ]]>
                </dc:creator>
                <pubDate>Tue, 18 Mar 2025 17:16:08 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742318086251/103cec5f-3330-4559-8554-4ec76b16ec76.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The web is a great place to access information and connect with people. It has opened up countless opportunities, making life more convenient in many ways.</p>
<p>But not everyone experiences the web in the same way. Websites are difficult to use for people who have visual, hearing, or mobility impairments. These barriers make it harder to navigate content, and in some cases, make the web completely inaccessible.</p>
<p>This handbook will help you understand accessibility and how to implement it. Whether you are a beginner or an intermediate developer, you'll learn basic accessibility practices and some advanced techniques. This will help you make your website more inclusive.</p>
<p>Let’s get started.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-accessibility">What is Accessibility?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-basic-accessibility-practices">Basic Accessibility Practices</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-semantic-and-non-semantic-html">Semantic and Non-Semantic HTML</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-text-content">Text Content</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-page-layouts">Page Layouts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-interactive-elements">Interactive Elements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-keyboard-accessibility">Keyboard Accessibility</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-form-labels">Form Labels</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-links">Links</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-table-accessibility">Table Accessibility</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-additional-css-and-javascript-practices">Additional CSS and JavaScript Practices</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-styling-form-elements">Styling Form Elements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-color-contrast">Color Contrast</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-javascript-practices">JavaScript Practices</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-advanced-accessibility-practices-wai-aria">Advanced Accessibility Practices: WAI-ARIA</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-the-role-attribute">The role attribute</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-aria--attribute">aria-* attribute</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-dynamic-content-attributes">Dynamic Content Attributes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-form-validation-and-errors">Form Validation and Errors</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-non-semantic-elements-as-buttons">Using non-semantic elements as buttons</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-multimedia-accessibility">Multimedia Accessibility</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-mobile-accessibility">Mobile Accessibility</a></p>
</li>
</ul>
<h2 id="heading-what-is-accessibility">What is Accessibility?</h2>
<p>Accessibility (A11y) is an important practice in web development that aims to make the website usable (accessible) for all people. This includes people who have disabilities that make it difficult for them to use websites. By making a website accessible to everyone, including people with disabilities, we ensure that they have the same opportunities as we do. We’re also helping to make the web a more inclusive place overall.</p>
<p>What kind of disabilities should we consider? In broad terms:</p>
<ul>
<li><p>Visual impairments: blindness, blurred vision, and colour blindness</p>
</li>
<li><p>Hearing impairments: low to no hearing</p>
</li>
<li><p>Mobility Impairments: difficulty with physical movement(s)</p>
</li>
<li><p>Cognitive Impairments: like Dyslexia and ADHD</p>
</li>
</ul>
<p>People with visual impairments commonly use devices like <a target="_blank" href="https://axesslab.com/what-is-a-screen-reader/">screen readers</a> to visualise and understand a website’s content, for example. So a big part of web accessibility is designing a website that can be easily accessed by a screen reader.</p>
<p>There are various practices that you, as a developer, can follow to make a website accessible, which I’ll cover in this handbook.</p>
<h2 id="heading-basic-accessibility-practices">Basic Accessibility Practices</h2>
<p>Accessibility is not just an added feature on top of a website you’ve already developed. It is a practice that needs to be followed throughout the development process. Whenever you are creating content on the web page, ask yourself if it is really accessible.</p>
<p>Another important point is that accessibility is not just for people with impairments. It benefits everybody by making a website easier to use, thus improving overall user experience.</p>
<p>How do you achieve good accessibility? Well, there are some practices that you should follow while writing HTML, CSS, and JavaScript code. We’ll discuss some basic practices in this section.</p>
<p>Before we get into it, let’s start by understanding what semantic and non-semantic HTML tags are:</p>
<h3 id="heading-semantic-and-non-semantic-html">Semantic and Non-semantic HTML</h3>
<p>Non-semantic HTML tags do not convey specific meaning or purpose. They can be used for anything, depending on the CSS styling and JavaScript functionality. Examples of non-semantic tags are: <code>&lt;div&gt;</code> and <code>&lt;span&gt;</code>. These tags are mostly used as containers for wrapping other elements.</p>
<p>Semantic HTML tags clearly describe their purpose to the browser and the developers through their names. They improve code readability and also help with <a target="_blank" href="https://seo.co/semantic-html/">SEO (Search Engine Optimisation)</a>. Examples of semantic tags include: <code>&lt;button&gt;</code>, <code>&lt;a&gt;</code>, <code>&lt;header&gt;</code>, <code>&lt;footer&gt;</code>.</p>
<p>You can find a list of all semantic elements <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantic_elements">here</a>.</p>
<h4 id="heading-importance-of-using-semantic-html">Importance of using semantic HTML</h4>
<p>An essential part of accessibility is using the correct HTML element for its intended purpose. This means, for example, using a <code>&lt;button&gt;</code> tag when you want to render a button.</p>
<p>But why use semantic elements? After all, you can use CSS to make a <code>&lt;div&gt;</code> look like a button. True, but using semantic elements is important for the following reasons:</p>
<ul>
<li><p>Semantic elements have built-in styles and functionality that you otherwise would need to add through CSS and JavaScript. This makes them easier to use.</p>
</li>
<li><p>They make the code easier to read and maintain, as you can actually see the elements being used rather than seeing a bunch of divs everywhere.</p>
</li>
<li><p>Screen readers can easily read and interpret semantic elements, helping people with visual impairments.</p>
</li>
</ul>
<p>In the following sections, we’ll understand basic accessibility practices for each type of content you render on HTML. We'll explore how to use the correct HTML tags for each situation, helping you see how choosing the right tag for its purpose improves accessibility.</p>
<p>Feel free to test each example with a screen reader. On Mac, use ⌘+F5 to activate VoiceOver, Mac’s built-in screen reader. For Windows, you can use the built-in screen reader called Narrator by pressing Ctrl + Windows Key + Enter.</p>
<h3 id="heading-text-content">Text Content</h3>
<p>When writing text content, it’s important to use the correct elements for headings, paragraphs, and lists. Let’s understand with the following examples.</p>
<p>Let’s say you write headings and paragraphs in the following way:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"heading1"</span>&gt;</span>Heading 1<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"heading2"</span>&gt;</span>Heading 2<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
This is one paragraph
<span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
This is another paragraph
</code></pre>
<p>This approach has the following problems:</p>
<ul>
<li><p>The screen reader won’t be able to distinguish between headings and paragraphs – it would just read out the contents in one go, thus confusing people who depend on screen readers.</p>
</li>
<li><p>It’s difficult to style individual paragraphs, since there are no selectors. Even if you add a <code>&lt;span&gt;</code> to each one, it requires extra CSS styling.</p>
</li>
<li><p>It also contains unnecessary line breaks which can be avoided by using the right elements.</p>
</li>
</ul>
<p>The above code is an example of bad semantics. This is what you should do instead:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Heading 1<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Heading 2<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is one paragraph<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is another paragraph<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>Here, we have used the right semantic elements for the text content, which has the following benefits:</p>
<ul>
<li><p>A screen reader is able to distinguish the headings from the paragraph text by reading out the heading level before reading the text.</p>
</li>
<li><p><code>h1</code>, <code>h2</code>, and <code>p</code> come with built-in styles and they each render on a new line. This eliminates the need to use line breaks.</p>
</li>
<li><p>The code looks cleaner and is much more readable.</p>
</li>
</ul>
<h4 id="heading-lists">Lists</h4>
<p>To render a list of items, we have the following approaches. The non-semantic approach just groups a bunch of divs together and applies CSS styles to them.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>TODO List<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"mylist"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Make Breakfast<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>Do Laundry<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>Complete blog post<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>Again, this achieves the desired output but it’s difficult for screen readers to identify this content as a list of items. Instead, use semantic elements:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>TODO List<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"mylist"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Make Breakfast<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Do Laundry<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Complete blog post<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>
</code></pre>
<p>This helps screen readers identify the element as an unordered list and read out each item. <code>&lt;ul&gt;</code> also comes with default styles and bullet points for each list item. You can also use <code>&lt;ol/&gt;</code> for numbered lists, where the screen reader reads out the number on each list item.</p>
<p>You can test the above examples with Mac’s VoiceOver to see the difference.</p>
<h4 id="heading-emphasized-text">Emphasized Text</h4>
<p>Emphasized text refers to highlighted text that gives importance to certain words or phrases within a piece of content. When adding emphasized text, it’s important to use the right semantic elements like <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong"><code>&lt;strong&gt;</code></a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em"><code>&lt;em&gt;</code></a>.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>For best results, use <span class="hljs-tag">&lt;<span class="hljs-name">em</span>&gt;</span>fresh ingredients<span class="hljs-tag">&lt;/<span class="hljs-name">em</span>&gt;</span> when cooking.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>The process of water turning into gas is called <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>evaporation<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>These elements add some built-in styles to the text like <em>bold</em> and <em>italic</em>. Also, if you test with VoiceOver, you’ll notice that it puts some emphasis on the text inside these elements. This helps people using screen readers identify emphasised text.</p>
<p>You may also add some colour to the emphasized text. But, there’s no need to add a lot of styles, else it may cause confusion. Visit <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Structuring_content/Emphasis_and_importance">MDN Docs-Emphasis and Importance</a> to learn more about text emphasis in HTML.</p>
<h4 id="heading-abbreviations">Abbreviations</h4>
<p>Next, when writing abbreviations (or acronyms), it’s a good practice to make them visually different and also include the full expansion of the acronym. You can also add some simple styling to the abbreviation. Learn more about abbreviations in <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Structuring_content/Advanced_text_features#abbreviations">MDN Docs-Abbreviations</a>.</p>
<h4 id="heading-other-best-practices">Other best practices</h4>
<p>Apart from the above, there are a few other practices that are good to follow:</p>
<ul>
<li><p>Use clear language, wherever possible. For example, expand abbreviations: instead of Jan, write January.</p>
</li>
<li><p>When writing ranges, avoid using dashes if possible, write 1 to 5 instead of 1-5.</p>
</li>
<li><p>Avoid using characters that may confuse users when a screen reader reads them out, for example <code>~</code> or <code>*</code>.</p>
</li>
<li><p>Avoid excessive exclamations and emojis.</p>
</li>
</ul>
<p>Also, when writing CSS for text content, remember these practices:</p>
<ul>
<li><p>When using styles like font sizes, line height, and letter spacing, ensure that the text is comfortable to read.</p>
</li>
<li><p>Your headings should stand out from the other text, in case you are using CSS styles. Usually, this is achieved by just using the right heading tags.</p>
</li>
<li><p>Text color should have 4.5:1 contrast with the background. See the <a class="post-section-overview" href="#heading-color-contrast">Color Contrast</a> section for details.</p>
</li>
</ul>
<p>If you want more tips on styling text, visit <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Text_styling">MDN Docs - CSS Text Styling</a>.</p>
<h3 id="heading-page-layouts">Page Layouts</h3>
<p>Page layout is concerned with how the content is laid out on the screen. When you start designing a web page, your first thought is how your content should be positioned on the screen.</p>
<p>Typically, a web page consists of a header, nav bar, footer, main content, and sidebar. In the <em>bad old days</em> (phrase borrowed from the docs, sorry), developers used tables to create page layouts consisting of these elements.</p>
<p>But tables made the layouts incredibly complex and hard to maintain. Table layouts are also difficult for screen readers to read, affecting accessibility.</p>
<p>Nowadays, there are much better ways to write page layouts. If you are including a header, nav bar, and footer along with the main content, you can use the following semantic elements:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Header<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- main navigation in here --&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Here is our page's main content --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- Main content here --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">footer</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- footer content in here --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
</code></pre>
<p>Let’s understand each tag used above (skip if you already know):</p>
<ul>
<li><p><code>&lt;header&gt;</code>: Represents the introductory section of a webpage, typically containing headings, logos, or navigation links.</p>
</li>
<li><p><code>&lt;nav&gt;</code>: Defines a navigation section that contains links to other parts of the website or page, providing easy access to important sections.</p>
</li>
<li><p><code>&lt;main&gt;</code>: Represents the main content area that focusses on the primary purpose of the page or the website, excluding common elements like header, footer, or sidebar (may include sidebar depending on the website).</p>
</li>
<li><p><code>&lt;footer&gt;</code>: Represents the bottom section of the web page, typically containing metadata, copyright information, or links to related resources.</p>
</li>
</ul>
<p>These elements are called <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element#content_sectioning">sectioning elements</a>. Following are advantages of using these elements:</p>
<ul>
<li><p>The layout is clear with each element clearly describing its purpose, making the code readable and maintainable.</p>
</li>
<li><p>Using the right semantic elements makes screen readers identify each part of the layout, thus helping visually impaired users understand how the website is structured.</p>
</li>
</ul>
<p>Of course, you can write the above layouts by using divs, but sectioning elements provide good semantics and help users understand the type of content they are navigating.</p>
<h3 id="heading-interactive-elements">Interactive Elements</h3>
<p>These consist of elements through which a user interacts with the web page. These elements include buttons, form fields, links, and so on.</p>
<h4 id="heading-keyboard-accessibility">Keyboard Accessibility</h4>
<p>Each interactive element on a web page should be navigable through the keyboard. This gives a user flexibility while navigating your website. Keyboard accessibility is really helpful for people with mobility impairments that may struggle to use a mouse.</p>
<p>For instance, visit <a target="_blank" href="https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html">this</a> page and try to navigate to each interactive element by pressing Tab on your keyboard. You can also press Enter/Spacebar to click on a button or a link. This should give you an idea of what a keyboard-accessible website looks like.</p>
<p>For the most part, using the right semantic elements should ensure keyboard accessibility, as they come with built-in functionality. Check out the following example:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
  Visit my blog at 
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.freecodecamp.org/news/author/KunalN25/"</span>&gt;</span>freecodecamp.org<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Click me<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>Click me again<span class="hljs-tag">&lt;/<span class="hljs-name">button</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">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter your name"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Here, we have used the correct semantic elements for the hyperlink, button, and input element. All these elements can be accessed through Tab and interacted with using Enter/Spacebar. Check out other form-related elements in this <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element#forms">list</a>.</p>
<p>Some people use a <code>div</code> or <code>span</code> and make them look like an anchor tag or a button with CSS styling. But this is bad for accessibility for two reasons:</p>
<ul>
<li><p><code>div</code> and <code>span</code> are not tab-able by default. So, even if you do make a <code>div</code> look like a button, the user cannot navigate to it using the keyboard.</p>
</li>
<li><p>Screen readers won’t be able to identify them as buttons, while in the case of semantic elements, they read these elements out as buttons or links.</p>
</li>
</ul>
<p>But if you absolutely have to use a <code>div</code> to create a clickable element, include the following attributes:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"customButton"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"0"</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Here, we have added two attributes, <code>tabindex</code> and <code>role</code>. We’ll understand the <code>role</code> attribute in a later section.</p>
<p>The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex"><code>tabindex</code></a> attribute takes an integer that specifies the tab order of tab-able elements, instead of the default top to bottom tab order. A positive integer means the element is focussed in an order specified by the attribute’s value.</p>
<p>But using tabindex to change the default tab order is not recommended, as it may cause confusion for keyboard navigators and affect accessibility. And frankly, it’s not necessary.</p>
<p>You should only ever use the following two values:</p>
<ul>
<li><p><code>tabindex=”0”</code> makes an element tab-able which means it can be accessed through a keyboard in the natural tab order.</p>
</li>
<li><p><code>tabindex=”-1”</code> means the element is not reachable via keyboard navigation.</p>
</li>
</ul>
<p>These attributes make the <code>div</code> behave like a button, but there’s a small piece of JS code you still need to add to make the button clickable via Enter/Return:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"customButton"</span>).addEventListener(<span class="hljs-string">"keydown"</span>, <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (event.key === <span class="hljs-string">"Enter"</span>) {
    <span class="hljs-built_in">document</span>.activeElement.click();
  }
});
</code></pre>
<p>Here, we have added an event listener to the element that listens for the keydown event. If the key pressed is Enter, then it calls the element’s <code>onclick</code> method.</p>
<p>If you are using a non-semantic element as a button, you need to add this extra code to make it work like a button. So, only use it if it's absolutely necessary. Otherwise, it's always better to use the correct semantic element in the first place.</p>
<p>Keyboard Accessibility is important for audio and video controls too. We’ll discuss this in the <a class="post-section-overview" href="#heading-multimedia-accessibility">Multimedia Accessibility</a> section.</p>
<h3 id="heading-form-labels">Form Labels</h3>
<p>A form label is some text that describes what you need to enter in a form field. Adding labels to form fields is a necessary practice since it lets the user know how to fill the form. But using the right semantic elements is important.</p>
<p>You could do the following and still achieve the desired output:</p>
<pre><code class="lang-xml">Enter name: <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
</code></pre>
<p>This is not good for screen reader users, as it does not read out what the input field is for. Even if it reads out “Enter name”, the user may not associate it with the input field. Instead, use the <code>&lt;label&gt;</code> element for form labels.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"name"</span>&gt;</span>Enter name:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"nameField"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>The <code>for</code> attribute associates the label with the input field. With this, when the screen reader’s focus is on the input field, it reads out the label, followed by “edit field” to let the user know they should enter their name in the input field.</p>
<p>Check out the <a target="_blank" href="https://mdn.github.io/learning-area/accessibility/html/good-form.html">form with the label</a> and <a target="_blank" href="https://mdn.github.io/learning-area/accessibility/html/bad-form.html">form without the label</a> in these examples for more clarity. Use Mac’s Voiceover (⌘+F5) or Windows’ Narrator (Ctrl+Windows+Enter) to see how it reads out the form elements.</p>
<p>Using <code>&lt;label&gt;</code> offers more advantages:</p>
<ul>
<li><p>By linking a <code>&lt;label&gt;</code> to an input field with the <code>for</code> attribute (clickable association), clicking on the label focuses on the input field.</p>
</li>
<li><p>Clickable association with input field helps the user’s select small inputs like <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox">checkboxes</a> or <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio">radio buttons</a>.</p>
</li>
<li><p>It follows semantic HTML and specifies that the text is being used as a form label.</p>
</li>
</ul>
<p>Lastly, remember that the label text should clearly describe what the user should enter into the field. For examples, “Enter name” or “Enter email”.</p>
<p>This applies to buttons as well. Ensure that button text is descriptive enough to tell the user what they are clicking on. Vague texts like “Click me!” or “Click here!” are not helpful. Examples of descriptive text are “Submit Form” or “Download Report” that give the users a clear idea of the button’s action.</p>
<p>Along with these, links also come under interactive elements. But since there are a lot of examples for Links, I’ll discuss them in their own section now.</p>
<h3 id="heading-links">Links</h3>
<p>Links are a key part of web pages as they allow the user to navigate the website. Links serve different purposes: going to a different page in the same website, going to an external website, or downloading something. In this section, you’ll learn about several practices with links that contribute towards accessibility.</p>
<h4 id="heading-linking-to-external-websites">Linking to External Websites</h4>
<p>When you add a link that lets users open an external website, including the <code>target=_blank</code> attribute opens the link in a new tab.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.wikipedia.org/"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>&gt;</span> Wikipedia <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</code></pre>
<p>This is helpful for users as they don’t need to exit the website, saving them from the hassle of navigating back to the website.</p>
<p>Also, if your link opens in a new tab, it’s a good idea to mention it so the screen readers can read it out and help visually impaired users.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.wikipedia.org/"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span> &gt;</span>
Wikipedia (opens in new tab)
<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</code></pre>
<p>Similarly, if your link opens a non-HTML file, like a pdf or docx, you should mention it:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"jan-salary-slip.pdf"</span>&gt;</span>
Salary-January (PDF)
<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</code></pre>
<p>Alternatively, you can use an icon to indicate a link opening in new tab.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://www.wikipedia.org/"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>&gt;</span>
  Wikipedia
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"new-tab-icon.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Opens in new tab"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"width:16px; height:16px; margin-left:5px;"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
</code></pre>
<p>When using an icon, make sure that you include the alt attribute with description about the image. We’ll understand its purpose in the <a class="post-section-overview" href="#heading-multimedia-accessibility">Multimedia Accessibility</a> section.</p>
<h4 id="heading-skip-links">Skip Links</h4>
<p>A skip link is a link element placed at the top of a page that links directly to the main content of the page. This allows the users to skip the headers and all the navigation menus, and directly jump to the main content of the page. This is helpful on websites where there’s lot of repetitive content on top like menus or banners.</p>
<p>Skip links are especially helpful for people who are visually impaired and who might be using screen readers. These links provide a way to bypass repetitive navigation menus and directly access the main content. This also helps keyboard navigators, thus saving time and enhancing the user experience.</p>
<p>To add a skip link, add an anchor tag at the very top, just under the body tag, and link it to the main content.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#main"</span>&gt;</span>Skip to main content<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Page Title<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/blog"</span>&gt;</span>Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-comment">&lt;!-- other nav links --&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"main"</span>&gt;</span>
      <span class="hljs-comment">&lt;!-- Main Content --&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>The skip link is keyboard accessible and is also read out by the screen reader. Clicking on it takes you straight to the main content. Visit <a target="_blank" href="https://webaim.org/">WebAIM</a> and press Tab on your keyboard to see skip links in action.</p>
<h4 id="heading-link-styling">Link Styling</h4>
<p>By default, links created with the anchor tag are visually different from non-link text. This is because the anchor tag has built-in styles like colour, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration">text-decoration</a>, focus-ring (displays when you tab on to the link with the keyboard) and hover effects.</p>
<p>Links should look different from the other text so they’re easily distinguishable. As you saw above, the browser does that for you, so you don’t need to do much. But if you are adding custom styles to the link that fit in better with your theme, you need to follow some best practices:</p>
<ul>
<li><p>Links should have different colors for default, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/:visited">visited</a>, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/:focus">focus</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/:hover">hover</a> states.</p>
</li>
<li><p>Link text color should be different from the non-link text and should have different styling.</p>
</li>
<li><p>Link text color should have a contrast of 3:1 between other text and 4.5:1 contrast between background color. See the <a class="post-section-overview" href="#heading-color-contrast">Color Contrast</a> section for more understanding</p>
</li>
</ul>
<p>An example of custom styling for links is shown below (from the Docs):</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">a</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#ff0000</span>;
}

<span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:hover</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">:focus</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#a60000</span>;
  <span class="hljs-attribute">text-decoration</span>: none;
}

<span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:active</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#000000</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#a60000</span>;
}
</code></pre>
<p>With the help of <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes">pseudo-classes</a>, this adds different styles for when link is hovered, previously visited, focussed (with the keyboard), or active (when the link is being clicked).</p>
<p>You can experiment with different colors and styles, but don’t remove the <code>cursor: pointer</code> or <code>outline</code> properties. Both are important for people using keyboard navigation.</p>
<p>Remember, links already have built-in styles for all the link states. Only add your own if you want something in line with your website’s theme.</p>
<h4 id="heading-avoid-using-onclick-handlers">Avoid using onclick handlers</h4>
<p>Links are used to navigate to another web page on the same website or navigate to an external website. Specifying the link in the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href">href</a> attribute does this for you without any need to add JavaScript code.</p>
<p>But some people add an <code>onclick</code> attribute to anchor elements, to make them behave like buttons and set <code>href=”#”</code> or <code>href="javascript:void(0)"</code> to avoid page refresh. This causes unexpected behaviour and may lead to the following problems:</p>
<ul>
<li><p>Copying or dragging this link adds an unnecessary <code>#</code> or <code>void(0)</code> to the URL, which does not make sense.</p>
</li>
<li><p>Clicking the link immediately scrolls the page to the top, which may lead to the user losing track of where they were.</p>
</li>
<li><p>If JavaScript is still downloading, clicking the link does nothing and the web page becomes unresponsive.</p>
</li>
</ul>
<p>It is also bad for semantics and accessibility, as people using screen readers may get confused. If you want to add JavaScript functionality on click of an element, just use a <code>&lt;button&gt;</code>. Only use links when navigating to a proper URL.</p>
<h4 id="heading-meaningful-link-text">Meaningful Link Text</h4>
<p>Similar to buttons, when writing link text, keep it meaningful and descriptive and avoid using “Click here” or “Click this”.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
  For more information about accessibility
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://developer.mozilla.org/en-US/docs/Web/Accessibility"</span>&gt;</span>
    click here
  <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>Instead of the above, do this:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
  For more information about accessibility, visit
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://developer.mozilla.org/en-US/docs/Web/Accessibility"</span>&gt;</span>
    MDN Docs - Accessibility
  <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>Check out the <a target="_blank" href="https://mdn.github.io/learning-area/accessibility/html/good-links.html">Good Links</a> and <a target="_blank" href="https://mdn.github.io/learning-area/accessibility/html/bad-links.html">Bad Links</a> examples from the docs. You can also test them with VoiceOver (⌘+F5).</p>
<h4 id="heading-link-proximity">Link Proximity</h4>
<p>If your web page has a lot of interactive elements like links and buttons, ensure that they are spaced properly to prevent accidental clicks. This helps people with <a target="_blank" href="https://axesslab.com/hand-tremors/">Motor Control Issues</a> that may click on the wrong link.</p>
<p>Using the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/margin"><code>margin</code></a> property should be enough to ensure spacing.</p>
<h3 id="heading-table-accessibility">Table Accessibility</h3>
<p>In the page layouts section, we saw that using tables for creating page layouts is an outdated practice. However, tables can still be used if you want to display a large amount of data in tabular form. Incorporating accessibility in tables helps screen readers interpret them and help visually impaired users.</p>
<p>Check out <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Structuring_content/Table_accessibility">MDN Docs - Table Accessibility</a> to understand best practices.</p>
<h2 id="heading-additional-css-and-js-practices">Additional CSS and JS Practices</h2>
<p>Most of your accessibility goals should be achieved with HTML alone. But there are certain things to keep in mind when writing CSS and JavaScript to ensure you don't break accessibility.</p>
<h3 id="heading-styling-form-elements">Styling Form Elements</h3>
<p>When styling form elements, remember the following:</p>
<ul>
<li><p>Do not remove the default styles for focus outlines, hover, and disabled state in form elements. You may modify them as per your site design, but they should still be visible.</p>
</li>
<li><p>Ensure that your labels and placeholder texts are visually clear. Follow colour contrast practices (next section).</p>
</li>
<li><p>For clickable areas like buttons and inputs, ensure they are large enough so the user can click comfortably.</p>
</li>
<li><p>Success and Error messages should be physically distinguishable from labels and other text content.</p>
</li>
</ul>
<h3 id="heading-color-contrast">Color Contrast</h3>
<p>When you choose colors for your website, your text and background colour should have a good colour contrast. A good color contrast ensures that the text is easily readable by all users (and it also helps people with color blindness in particular).</p>
<p>The WCAG (Web Content Accessibility Guidelines) recommends the following contrast ratios:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736175276741/40ee7fe4-110c-4dd1-95f3-4cb7620de032.png" alt="Recommended Color contrast ratios" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Let’s understand the colour contrast ratings:</p>
<ul>
<li><p>AA rating refers to the minimum ratio your colour contrast should be such that the site’s content is readable. As you can see in the table above, this requires a 4.5:1 minimum ratio for body text, a 3:1 ratio for large-scale text, and a 3:1 ratio for active user interface components and graphical objects.</p>
</li>
<li><p>AAA rating is the ideal standard for accessibility that ensures high contrast for your website. This requires a 7:1 ratio for body text, a 4.5:1 ratio for large-scale text, and isn’t defined for UI components/graphical objects.</p>
</li>
</ul>
<p>Choose a contrast ratio that aligns well with your design, but try to keep it to at least AA rating. To check colour contrast ratio between two colors, you can use the following tools:</p>
<ul>
<li><p><a target="_blank" href="https://webaim.org/resources/contrastchecker/">Color Contrast Checker</a></p>
</li>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/devtools/accessibility/contrast">Chrome Developer Tools</a> - Identifies text in your website not meeting AA and AAA ratings</p>
</li>
</ul>
<h3 id="heading-javascript-practices">JavaScript Practices</h3>
<h4 id="heading-mouse-specific-events">Mouse-specific events</h4>
<p>When you have functionality triggered by events like <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseover_event">mouse-over</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseout_event">mouse-out</a>, they cannot be accessed by people that depend on keyboard navigation. So, to make the functionality accessible by keyboard, you need to add the same event handlers to events like <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event">focus</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event">blur</a>.</p>
<h4 id="heading-client-side-form-validations">Client side form validations</h4>
<p>When you submit data through a form, the data is validated to check if you have entered valid data. Often, when the data is sent to the server, the server validates the data and lets the UI know if the validation has failed.</p>
<p>To make the website user-friendly, it helps to add form validations on the client-side, so users can get instant feedback if they have entered incorrect data, since the server-side mechanism may take time. This is a very small step towards improving user experience.</p>
<p>Check out the <a target="_blank" href="https://mdn.github.io/learning-area/accessibility/css/form-validation.html">Form Validation</a> Example to understand more.</p>
<p>Apart from the above, one thing you should remember is not to use JavaScript for anything and everything. JavaScript can be used to generate any form of HTML and dynamically apply CSS styling. It is very helpful if you have dynamic content on your website.</p>
<p>But if you have too much HTML generated by JavaScript, it gets hard for screen readers to keep track of the dynamic changes. This makes the website difficult to read for impaired users. So, make sure you don't overuse JavaScript when simple HTML would be enough.</p>
<p>Accessibility for dynamic content updates is covered in the next section.</p>
<h2 id="heading-advanced-accessibility-practices-wai-aria">Advanced Accessibility Practices: WAI-ARIA</h2>
<p>As applications started to get bigger and more complex, developers started needing a new set of accessibility features. Semantic elements alone were not enough, especially for complex elements like date pickers and custom widgets.</p>
<p>Depending on semantic HTML does not help when content is updated dynamically on the web page. Nowadays, all websites built with JavaScript have content that isn’t loaded initially, but updated dynamically based on user interactions.</p>
<p>WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) was introduced to add more accessibility features wherever they were needed. It defines a set of HTML attributes that you can use to provide additional semantics to your website and improve accessibility.</p>
<p>In the following sections, you’ll learn which attributes were introduced and how you can use them to enhance accessibility.</p>
<h3 id="heading-the-role-attribute">The <code>role</code> attribute</h3>
<p>The <code>role</code> attribute helps add semantic information to non-semantic elements by defining their “role” on the web page. With roles, screen readers can accurately read non-semantic elements and help identify them for people with disabilities.</p>
<p>W3C defines several roles that you can use, depending on their purpose. But keep in mind that you should only use <code>role</code> when necessary. In most cases, it’s better to just use the right semantic elements like <code>&lt;button&gt;</code>, <code>&lt;nav&gt;</code>, <code>&lt;header&gt;</code>, and so on.</p>
<p>But, when semantic elements are not fulfilling your purpose, roles can help. So, let’s understand how to use them with some examples:</p>
<p>If you want to create a button with custom <code>div</code>, adding the <code>role</code> attribute specifies that this element is being used as a button.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"0"</span>&gt;</span>Click Me<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>When you test this with Mac’s VoiceOver (⌘+F5), it reads out the element as a button. As discussed before, always include the <code>tabindex</code> attribute.</p>
<p>But if you want to use a <code>div</code> instead of a button, you still need to add JavaScript functionality, as explained in the the <a class="post-section-overview" href="#heading-keyboard-accessibility">Keyboard Accessibility</a> section.</p>
<p>Another example is if you are writing a custom link. You can use the following role, so that the screen reader interprets this as a link:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"link"</span>&gt;</span>Visit our website<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Apart from interactive elements, <code>role</code> attribute can also be used to define elements as navigation menus, side bars, banners, etc. If you are using non-semantic elements for these purposes, always include a role, like the following:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"navigation"</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Navigation menu items --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>In this case, the screen reader announces this as a navigation area.</p>
<p>Also, if you have an element that serves as an alert for the user, including the following role makes the screen reader announce it as soon as it shows up on the screen, even if it doesn’t have focus:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
  Please respond to this alert
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>You can find the full list of available roles at <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles">MDN Docs: WAI-ARIA Roles</a>.</p>
<h3 id="heading-aria-attributes">aria-* attributes</h3>
<p>Apart from <code>role</code>, ARIA (Accessible Rich Internet Applications) defines extra attributes to enhance the accessibility of web applications. These attributes give screen readers more information about elements, helping people with disabilities better understand them.</p>
<p>If native semantic elements or the <code>role</code> attribute alone are not sufficient, aria-* attributes can provide extra context. You can find a full list of these attributes in <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes">MDN Docs-ARIA</a>.</p>
<p>In the following sections, we’ll see how role and aria-* attributes can improve accessibility. We won’t cover all the attributes here, but we’ll focus on the most commonly used ones.</p>
<h3 id="heading-dynamic-content-updates">Dynamic Content Updates</h3>
<p>When a web page loads for the first time, its content is read out by the screen reader. But screen readers cannot capture dynamic content, that is content that gets added or removed.</p>
<p>For example, when a web page is showing live sport updates, it gets updated almost every minute. Screen readers will only read out the content displayed when the page is first rendered, but don’t show dynamic updates.</p>
<p>This is not really a problem for many users, but for people with visual impairments, screen readers may not be able to read the changes on the page. Most modern websites are dynamic in nature, so it’s important to consider accessibility of dynamic content updates.</p>
<p>Check out the <a target="_blank" href="https://mdn.github.io/learning-area/accessibility/aria/aria-no-live.html">aria-no-live</a> example from MDN Docs. It loads a new quote every 10 seconds, which you can see clearly as a user with no visual impairment. But the screen reader only reads the initial page content and does not announce the updates. This is not good for accessibility.</p>
<p>To fix this, WAI-ARIA provides the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-live"><code>aria-live</code></a> attribute that makes the screen reader read out content that is updated. You can add this attribute to the element that contains the dynamic content.</p>
<p>It takes the following three values:</p>
<ul>
<li><p><code>aria-live="off"</code>: Default value that means no content is read out</p>
</li>
<li><p><code>aria-live="polite"</code> Updates only announced when the user is idle</p>
</li>
<li><p><code>aria-live="assertive"</code>: Content read out as soon as it is updated.</p>
</li>
</ul>
<p>Depending on the importance of the update, you can decide which value to use.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">aria-live</span>=<span class="hljs-string">"polite"</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Dynamic Content here --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>In this case, the screen reader waits till the user is done with their current task before announcing the update.</p>
<p>You can add more detail here. With the above attribute, only the text that is updated is read out. But, screen reader users may get confused as to which part of the page is being read out. So, it is helpful if the entire element is read out.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">aria-live</span>=<span class="hljs-string">"assertive"</span> <span class="hljs-attr">aria-atomic</span>=<span class="hljs-string">"true"</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Dynamic Content here --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-atomic"><code>aria-atomic</code></a> attribute tells screen readers to read out the entire element as a single atomic unit. This avoids confusion for visually impaired users. Check out the <a target="_blank" href="https://mdn.github.io/learning-area/accessibility/aria/aria-live.html">aria-live</a> example from MDN Docs with Mac’s VoiceOver (⌘+F5). It reads out the entire element when the content is updated.</p>
<h3 id="heading-form-validation-and-errors">Form Validation and Errors</h3>
<p>Let’s say you have added some validation to your form through JavaScript. When the validation fails, an error message gets added on the screen. For example, a required message shows up if you have missed a field.</p>
<p>The implementation for error handling involves creating an element containing an error message or a list of errors that render on certain conditions, depending on the JavaScript code. Just as we discussed in the previous section, the screen reader does not read out new content updates.</p>
<p>So, we should make sure that the screen reader reads out the error message as soon as it shows up, to let visually impaired users know that an error has been thrown. We can use the following attributes for this purpose:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"errors"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span> <span class="hljs-attr">aria-relevant</span>=<span class="hljs-string">"all"</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">ul</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/alert_role"><code>alert</code></a> role does two things. It semantically identifies this element as a piece of important information. Secondly, this role turns the element into a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions">live</a> region which means the screen reader is notified immediately if there are any changes.</p>
<p>The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-relevant"><code>aria-relevant</code></a> attribute describes what changes need to be announced in a live region. The attribute takes a space-separated list of the following values:</p>
<ul>
<li><p><code>additions</code>: Announces new content added to the live region</p>
</li>
<li><p><code>removals</code>: Content removed from the live region is read out</p>
</li>
<li><p><code>text</code>: Announces any modifications to existing content.</p>
</li>
</ul>
<p>It also takes a value <code>all</code> which is a shorthand for <code>additions removals text</code>, meaning all three types of content are read out.</p>
<p>You can check the <a target="_blank" href="https://mdn.github.io/learning-area/accessibility/css/form-validation.html">Form Validation Example</a> from the MDN Docs.</p>
<p>Next, let’s see what to do if we want to mark certain fields as required. Normally, we’d add visual cues like a <code>*</code> and the following message at the top of the form:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Fields marked with an asterisk (*) are required.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>This is helpful for regular users, but visually impaired users may get confused as to which fields are required. To make it easier for them, we can use the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-required"><code>aria-required</code></a> attribute.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">aria-required</span>=<span class="hljs-string">"true"</span> /&gt;</span>
</code></pre>
<p>With this attribute, the screen reader mentions this field as “required” while reading it out.</p>
<p>When you are creating input fields, it’s important to include a label, as some screen readers do not read out placeholder text. If you don’t want to include a label field, here are the following alternatives:</p>
<p>You can use the <code>aria-label</code> attribute to add labels to input fields that do not have a label associated with them.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Enter email"</span> /&gt;</span>
</code></pre>
<p>This attribute provides some text to be read out by a screen reader to describe the input field.</p>
<p>You can go one step further and use the <code>aria-labelledby</code> attribute that uses another element to act as a label for the input field. For example:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"emailLabel"</span>&gt;</span>Enter your email<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">aria-labelledby</span>=<span class="hljs-string">"emailLabel"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>The screen reader reads out the text inside the <code>&lt;span&gt;</code> element to describe the input element. This is similar to having a <code>&lt;label&gt;</code> with a <code>for</code> attribute. You can also use this attribute to reference other interactive elements like <code>&lt;button&gt;</code> or <code>&lt;a&gt;</code> that do not have a label field to reference them.</p>
<p>Keep in mind that the <code>aria-labelledby</code> attribute only defines an accessible name for the element – it does not provide other functionality like clicking on the label to focus on the input element. It’s better to use <code>&lt;label&gt;</code> with a <code>for</code> attribute.</p>
<p>We have already discussed form labels in the <a class="post-section-overview" href="#heading-interactive-elements">Interactive Elements</a> section.</p>
<p>You’ve now seen some of the different attributes that WAI-ARIA offers and how they enhance accessibility. You can visit <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/WAI-ARIA_basics#accessibility_of_non-semantic_controls_2">MDN Docs: WAI-ARIA</a> to check out additional details I may have missed.</p>
<p>Before we move on, remember one thing: <em>use WAI-ARIA only when necessary</em>. Usually, semantic elements are able to achieve majority of your accessibility goals. Don’t over-use WAI-ARIA as they might end up complicating your code.</p>
<h2 id="heading-multimedia-accessibility">Multimedia Accessibility</h2>
<p>A website’s content is not restricted to text. It also often consists of multimedia content like images, audio, and video. In a lot of cases, multimedia content is easier to understand than text content. While this is true for many users, it poses challenges for users with disabilities.</p>
<p>People with visual impairments cannot see images and people who are deaf or hard of hearing cannot easily interpret audio content. So, as developers, it’s our job to make this type of content accessible for everyone. Let’s understand how to make this possible:</p>
<h3 id="heading-images">Images</h3>
<p>Since people with visual impairments cannot see images, they depend on a screen reader to describe the image. Just writing an <code>img</code> tag with <code>src</code> attribute does not help.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"temple.jpg"</span> /&gt;</span>
</code></pre>
<p>By default, the screen reader reads out the file path or URL of the image. A file name might give some idea of the image, but still does not describe it.</p>
<p>So, it’s helpful to add an <code>alt</code> attribute to an <code>img</code>. The <code>alt</code> attribute provides an alternate text for the image, and its purpose is to describe the image.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span>
  <span class="hljs-attr">src</span>=<span class="hljs-string">"temple.jpg"</span>
  <span class="hljs-attr">alt</span>=<span class="hljs-string">"The Meenakshi Temple, situated in Madurai, a South Indian City is dedicated to goddess Meenakshi, a form of Parvati"</span>
/&gt;</span>
</code></pre>
<p>Here, instead of reading the file path, the screen reader reads out the alternate text – that is, the value of the <code>alt</code> attribute. The alternate text should provide a description of the image to help users understand what it’s conveying. So, instead of just saying “Temple”, the user knows which temple is being depicted in the image.</p>
<p>You can also add extra context to the image with the <code>title</code> attribute.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span>
  <span class="hljs-attr">src</span>=<span class="hljs-string">"temple.jpg"</span>
  <span class="hljs-attr">alt</span>=<span class="hljs-string">"The Meenakshi Temple, situated in Madurai, a South Indian City is dedicated to goddess Meenakshi, a form of Parvati"</span>
  <span class="hljs-attr">title</span>=<span class="hljs-string">"The Meenakshi Temple"</span>
/&gt;</span>
</code></pre>
<p>When focussed on the image, the screen reader reads out the <code>alt</code> text and the title.</p>
<p>Let’s take another example which uses an alternative to the <code>alt</code> attribute:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"temple.jpg"</span> <span class="hljs-attr">aria-labelledby</span>=<span class="hljs-string">"temple-label"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"temple-label"</span>&gt;</span>
  The Meenakshi Temple, situated in Madurai, a South Indian City is dedicated to
  goddess Meenakshi, a form of Parvati
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>Here, instead of using the <code>alt</code> attribute, we have used the <code>aria-labelledby</code> attribute to link the paragraph element to the image. The text inside <code>p</code> acts as an alternate text for the image. This is helpful if you need to use the same text as an alternate text for different images.</p>
<p>Sometimes, we use images as icons for headers and navigation menus, just for decoration. Usually, these images are not relevant to understand the content of the page. In these cases, you add an empty <code>alt</code> attribute.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"page-icon.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span>
  History of Meenakshi Temple 
<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
</code></pre>
<p>If you skip the <code>alt</code> attribute, the screen reader reads out the entire image URL. To avoid this, use an empty <code>alt</code> attribute, so the screen reader simply announces it as an image and moves on, preventing unnecessary distractions for users.</p>
<p>You can also use <code>role=”presentation”</code> to skip reading the image path or alternative text.</p>
<h3 id="heading-audio-and-video">Audio and video</h3>
<p>When using the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio">&lt;audio&gt;</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video">&lt;video&gt;</a> elements, remember to include multiple sources – that is, provide the audio and video in different formats. For browsers that do not support the formats you have mentioned, include a fallback download link so they can access the resource.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">audio</span> <span class="hljs-attr">controls</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"audio.mp3"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"audio/mpeg"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"audio.ogg"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"audio/ogg"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
    Your browser doesn't support HTML video. Here is a
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"video.mp3"</span>&gt;</span>link to the video<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> instead.
  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">audio</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">video</span> <span class="hljs-attr">controls</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"video.mp4"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"video/mp4"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"video.webm"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"video/webm"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
    Your browser doesn't support HTML5 video. Here is a
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"video.mp4"</span>&gt;</span>link to the video<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> instead.
  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">video</span>&gt;</span>
</code></pre>
<p>Next, let’s understand the shortcomings of using native HTML controls for audio and video.</p>
<ul>
<li><p>They cannot be styled with CSS, so they may not align with your website’s theme.</p>
</li>
<li><p>The play/pause buttons are not keyboard accessible.</p>
</li>
<li><p>They don’t have functionality to forward or rewind the video.</p>
</li>
</ul>
<p>To overcome these limitations, we’ll create our custom video player in the next steps. To start, let’s create a container for the video content:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"controls"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"play-pause"</span>&gt;</span>Play<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">class</span>=<span class="hljs-string">"stop"</span>&gt;</span>Reset Video<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>These will work as the play/pause and reset buttons. Then, let’s remove the <code>controls</code> attribute from the <code>&lt;video&gt;</code> to replace them with our custom controls.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> videoPlayer = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"video"</span>);
videoPlayer.removeAttribute(<span class="hljs-string">"controls"</span>);
</code></pre>
<p>Why do we remove it at run time? Let’s say JavaScript does not load due to some issue. In this case, the user can still use the native controls. Next, let’s add some functionality to our buttons:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> playPauseBtn = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".play-pause"</span>);
<span class="hljs-keyword">const</span> resetBtn = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".reset"</span>);

playPauseBtn.onclick = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">if</span> (videoPlayer.paused) {
    videoPlayer.play();
    playPauseBtn.textContent = <span class="hljs-string">"Pause"</span>;
  } <span class="hljs-keyword">else</span> {
    videoPlayer.pause();
    playPauseBtn.textContent = <span class="hljs-string">"Play"</span>;
  }
};

resetBtn.onclick = <span class="hljs-function">() =&gt;</span> {
  videoPlayer.pause();
  videoPlayer.currentTime = <span class="hljs-number">0</span>;
  playPauseBtn.textContent = <span class="hljs-string">"Play"</span>;
};
</code></pre>
<ul>
<li><p>The video player object is of type <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement"><code>HTMLMediaElement</code></a>, that contains several methods you can use to control the video.</p>
</li>
<li><p>For the play/pause button, we add a toggling functionality, with the <code>play()</code> and <code>pause()</code> methods.</p>
</li>
<li><p>To reset the video, we pause it and set the current time to 0.</p>
</li>
</ul>
<p>Now, our custom video player is keyboard accessible, and able to be styled with CSS. You can also add additional functionality like forward/rewind, a timer, and a progress bar. The steps are similar for a custom audio player.</p>
<p>Check out the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/Multimedia#creating_custom_audio_and_video_controls">MDN Docs</a> for more detail about this functionality.</p>
<h4 id="heading-audio-transcripts">Audio Transcripts</h4>
<p>People who are deaf or hard of hearing cannot easily access audio content. So to make it accessible, you need to add transcripts under any audio or video form of content.</p>
<p>If you run a business, you could pay a professional to do the transcripts. Check out the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/Multimedia#audio_transcripts">docs</a> for options. To show the transcript on the UI, you could use a show/hide panel. Referring to the docs, see the <a target="_blank" href="https://mdn.github.io/learning-area/accessibility/multimedia/audio-transcript-ui/">audio transcript UI</a> (<a target="_blank" href="https://github.com/mdn/learning-area/tree/main/accessibility/multimedia/audio-transcript-ui">source code</a>) for an example.</p>
<p>If the audio is a recording of some presentation, you should attach links to any documents or presentation decks. Also, include a description for any visual content being referenced.</p>
<h4 id="heading-video-closed-captioning-and-subtitles">Video Closed Captioning and Subtitles</h4>
<p>First, let’s understand the difference between captions and subtitles. They are implemented in a similar way and visually, they look the same – but their purposes are different.</p>
<p>Captions denote who’s speaking and describe other sound effects in the video. They are mostly added with people who are deaf or hard of hearing in mind. Subtitles help people who don’t understand the language being spoken in the video, by translating it to text that uses the language of their choice.</p>
<p>Let’s see how to add subtitles to your videos. We write subtitles in WebVTT, a format that contains text along with the range of timestamps indicating which text you want in each part of the video. Following is an example of a subtitles file:</p>
<pre><code class="lang-javascript">WEBVTT

<span class="hljs-number">1</span>
<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">01.230</span> --&gt; <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02.606</span>
This is the first subtitle.

<span class="hljs-number">2</span>
<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">04.739</span> --&gt; <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">06.074</span>
This is the second.
</code></pre>
<p>Save this file and name it with a <code>.vtt</code> extension. To link this file to your video, include it in a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track"><code>&lt;track&gt;</code></a> element:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">video</span> <span class="hljs-attr">controls</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"video.mp4"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"video/mp4"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">track</span>
    <span class="hljs-attr">src</span>=<span class="hljs-string">"captions.vtt"</span>
    <span class="hljs-attr">kind</span>=<span class="hljs-string">"subtitles"</span>
    <span class="hljs-attr">srclang</span>=<span class="hljs-string">"en"</span>
    <span class="hljs-attr">label</span>=<span class="hljs-string">"English"</span>
    <span class="hljs-attr">default</span>
  /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">video</span>&gt;</span>
</code></pre>
<p>You should include the <code>&lt;track&gt;</code> element inside the <code>&lt;video&gt;</code> element and placed after all the sources. It has the following attributes:</p>
<ul>
<li><p><code>kind</code> mentions the type of file being referenced.</p>
</li>
<li><p><code>srclang</code> indicates the language the subtitles are in.</p>
</li>
<li><p><code>label</code> indicates the text that is shown while the user is selecting a language</p>
</li>
<li><p><code>src</code> is the path or URL of the subtitles file, that is the <code>.vtt</code> file we created previously.</p>
</li>
</ul>
<p>This will show subtitles for the specified timestamps. This will not only help people with hearing impairments, but is also useful for people who don’t understand the language, or those who are working in a noisy environment.</p>
<p>For people who are visually impaired, you could also include text that describes certain visuals in parts of the video. This text would be read out by screen reader.</p>
<p>You can also add custom styling to subtitle menu and subtitle text. Check out <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Audio_and_video_delivery/Adding_captions_and_subtitles_to_HTML5_video">MDN Docs - Adding captions and subtitles to HTML video</a> for the implementation.</p>
<h2 id="heading-mobile-accessibility">Mobile Accessibility</h2>
<p>We have covered many key accessibility practices so far, and they should work well on mobile phones as well. But there are some additional considerations you can follow for mobile users.</p>
<p>First, let’s talk about mouse-specific events. We have already seen how to make mouse-specific events accessible in the <a class="post-section-overview" href="#heading-javascript-practices">JavaScript Practices</a> section. Events like <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/mousedown_event">mousedown</a> or <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseup_event">mouseup</a> are often used for drag and drop functionalities.</p>
<p>But these are not accessible for touchscreen users, so you should add the same functionality to touch-specific events like <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/touchstart_event">touchstart</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Element/touchend_event">touchend</a>. The following example is in the context of drag and drop:</p>
<pre><code class="lang-javascript">source.ontouchstart = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  <span class="hljs-comment">// initiate drag</span>
};

dest.ontouchend = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
   <span class="hljs-comment">// drop</span>
};
</code></pre>
<p>Next, you have to ensure that you are following responsive design when designing your web pages. Responsive designs make sure the website looks good on both desktop and mobile phones. I have written a detailed guide on <a target="_blank" href="https://medium.com/gitconnected/read-this-to-make-your-website-responsive-35af4ab7992b">responsive design</a>, so check it out if you are interested.</p>
<p>Some other mobile accessibility practices that are good to know:</p>
<ul>
<li><p>Do not disable zoom on your website. Both fully-sighted users as well as those who have visual impairments may need to zoom in to read the website’s content on smaller screens.</p>
</li>
<li><p>When writing navigation menus, you’d normally conceal it and provide a hamburger icon to open it, as the screen is much shorter/smaller on a mobile phone. In these cases, the hamburger menu should be easily accessible. Check out the example of a <a target="_blank" href="https://fritz-weisshart.de/meg_men/">good hamburger menu</a> from the docs, in mobile view.</p>
</li>
<li><p>When creating forms, try to minimise the amount of typing the user needs to do, as it can get annoying for mobile users. This is especially important if your website is primarily designed for mobile users. Check out the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/Mobile#user_input">docs</a> for examples.</p>
</li>
</ul>
<p>Visit <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/Mobile">MDN Docs-Mobile Accessibility</a> if you want to learn more.</p>
<h2 id="heading-testing-accessibility-with-tools">Testing Accessibility with Tools</h2>
<p>There are several tools you can use to test the accessibility of your page. <a target="_blank" href="https://developer.chrome.com/docs/lighthouse/overview">Lighthouse</a> in Chrome Developer Tools is an open source tool that analyses a web page for performance, accessibility, SEO, and more. It generates a report on how a page performs in these areas.</p>
<p>Let’s see how it helps in analysing the accessibility of a page:</p>
<p>Open Chrome Dev Tools and navigate to the Lighthouse tab. Click on “Analyse Page Load” and wait for a few seconds. It will show a report that contains info on how your web page scored on Accessibility and other metrics. It will list down any accessibility issues you may have.</p>
<p>Let’s take the following example:</p>
<pre><code class="lang-xml"><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">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"image.jpg"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"2"</span>&gt;</span>Click Here<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"alert('Clicked!')"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"button"</span>&gt;</span>Click Me<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>When tested with the Lighthouse audit, it yields the following results:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739631885589/c886f304-aba2-44ac-8d75-88fac2f60c55.png" alt="Lighthouse audit with accessibility issues" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>As you can see, it’s scored 74 on accessibility, meaning there is room for improvement. It has also shown the accessibility issues within your HTML code, as you might have guessed looking at the code:</p>
<ul>
<li><p>Image elements do not have <code>alt</code> attribute</p>
</li>
<li><p>Form input does not have a label</p>
</li>
<li><p><code>tabindex</code> value is greater than 0.</p>
</li>
</ul>
<p>Let’s correct these issues and run the test again:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739632090527/2db4798a-53d3-4010-9756-83de8b0f208a.png" alt="Lighthouse audit with good accessibility" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>This time, it has scored 100 on Accessibility since we have followed all the basic practices.</p>
<p>As you can see, this is a really simple HTML page, and it’s much harder to achieve a score of 100 for large websites. But, you should aim to achieve as high a score as possible. This shouldn’t be too challenging if you make accessibility a part of your development process.</p>
<p>The accessibility score on it’s own does not mean your website is fully accessible. You also need to test the following:</p>
<ul>
<li><p>Manual testing with a screen reader (Mac’s Voiceover or Windows’ Narrator).</p>
</li>
<li><p>Keyboard accessibility – test whether each and every part of your website is keyboard accessible</p>
</li>
<li><p>Simulating your website with different color contrasts for different visual impairments.</p>
</li>
</ul>
<p>For simulating, Chrome Developer Tools provides a Rendering tool to emulate your website on different preferences, like light/dark mode, high/low color contrast, reduced motion and various visual impairments.</p>
<p>To access it, open Developer Tools, do ⌘+shift+P (Ctrl+Shift+P on Windows) and type “Rendering”. It will open the following window:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741959781294/36f6c233-9326-4acb-a551-e95a56a87d8a.png" alt="Rendering tool" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>If you have added media queries like the following, you can select these preferences and test whether your website behaves accordingly:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> (prefers-reduced-motion) {
    * {
        <span class="hljs-attribute">animation</span>: none;
    }
}
</code></pre>
<p>So, when you select <code>prefers-reduced-motion</code>, you can test if all the animations have been disabled, and how your website functions.</p>
<p>Apart from the Developer Tools, there’s an NPM plugin called <a target="_blank" href="https://www.npmjs.com/package/eslint-plugin-jsx-a11y">eslint-plugin-jsx-a11y</a> that evaluates React JSX code for accessibility issues.</p>
<p>You can find all the code snippets on <a target="_blank" href="https://github.com/KunalN25/accessibilityguide">GitHub</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Accessibility isn’t just a feature added on top of your code – it should be a part of the development process. When you make a website accessible to everyone, it not only increases your user base, but also promotes inclusivity.</p>
<p>Even though the primary benefactors of accessibility are people with disabilities, it also benefits other users by making the website easier to use overall. A lot of the practices mentioned in the article, like using semantic elements, adding the right attributes, and so on are very easy to follow and go a long way towards ensuring accessibility.</p>
<p>If you are a beginner, you have already done a great job learning about accessibility. Start including simple accessibility practices in your projects. Over time, including these practices will become a natural habit.</p>
<p>I hope this handbook becomes your go-to resource for anything related to accessibility. If you think I've missed something or need clarification on any concepts, feel free to reach out to me on Twitter. For more content on web development, check out out my profile.</p>
<h3 id="heading-references">References</h3>
<ul>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility">MDN Docs-Accessibility</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=2oiBKSjOOFE">Web Dev Simplified- Guide on Accessibility</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Breakpoints for Responsive Web Design ]]>
                </title>
                <description>
                    <![CDATA[ Breakpoints are fundamental to the concept of responsive web design. They enable websites to adapt seamlessly across different devices and screen sizes.  Breakpoints mark the points at which a website's layout and content should change to ensure opti... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/breakpoints-for-responsive-web-design/</link>
                <guid isPermaLink="false">66c4c3b8e486f65d4125b7f9</guid>
                
                    <category>
                        <![CDATA[ responsive design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joan Ayebola ]]>
                </dc:creator>
                <pubDate>Mon, 24 Jun 2024 18:03:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/Ivory-and-Blue-Lavender-Aesthetic-Photo-Collage-Presentation--13-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Breakpoints are fundamental to the concept of responsive web design. They enable websites to adapt seamlessly across different devices and screen sizes. </p>
<p>Breakpoints mark the points at which a website's layout and content should change to ensure optimal user experience on devices ranging from smartphones and tablets to desktop computers. </p>
<p>It's really important for today's web designers to know how breakpoints work and use them smartly. This helps them create websites that work well on all kinds of devices and are easy for people to use.</p>
<p>In this article, we'll explore breakpoints in detail: why they matter, how to use them effectively, and their role in making websites adjust smoothly to different screen sizes.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-responsive-web-design-rwd">What is Responsive Web Design?</a></li>
<li><a class="post-section-overview" href="#heading-why-are-breakpoints-important-in-rwd">Why are Breakpoints Important in RWD?</a></li>
<li><a class="post-section-overview" href="#heading-common-breakpoint-ranges-for-responsive-design-2024">Common Breakpoint Ranges for Responsive Design (2024)</a></li>
<li><a class="post-section-overview" href="#heading-factors-to-consider-when-choosing-the-right-breakpoints-for-your-project">Factors to Consider When Choosing the Right Breakpoints for Your Project</a></li>
<li><a class="post-section-overview" href="#heading-basic-structure-of-a-media-query">Basic Structure of a Media Query</a></li>
<li><a class="post-section-overview" href="#heading-advanced-breakpoint-techniques">Advanced Breakpoint Techniques</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-what-is-responsive-web-design-rwd">What is Responsive Web Design (RWD)?</h2>
<p>Responsive Web Design (RWD) is an approach to web design that ensures web pages render well on a variety of devices and window or screen sizes. </p>
<p>It involves using fluid grids, flexible images, and CSS media queries to automatically adapt the layout and content of a website to the device's screen size and orientation. </p>
<p>The goal of responsive web design is to provide an optimal viewing and interaction experience, ensuring easy reading and navigation with minimal resizing, panning, and scrolling across a wide range of devices, from desktop computers to mobile phones.</p>
<h2 id="heading-why-are-breakpoints-important-in-rwd">Why are Breakpoints Important in RWD?</h2>
<p>Breakpoints are important in Responsive Web Design (RWD) because they define specific points where a website's layout and content should adapt to different screen sizes and devices. </p>
<p>Here’s why they are crucial:</p>
<h3 id="heading-device-compatibility">Device Compatibility</h3>
<p>Breakpoints enable websites to adjust their design and layout to ensure compatibility with various devices like smartphones, tablets, laptops, and desktops. This adaptability ensures that users have a consistent and optimized experience regardless of the device they use.</p>
<h3 id="heading-optimal-user-experience">Optimal User Experience</h3>
<p>Designers can use breakpoints to tailor the presentation of content, navigation, and functionality based on screen size. This customization enhances user experience by ensuring content is readable, accessible, and easy to interact with across devices.</p>
<h3 id="heading-fluidity-in-design">Fluidity in Design</h3>
<p>Instead of creating fixed-width designs that may not scale well, breakpoints allow for fluid grids and flexible elements. This approach ensures that the design remains visually appealing and functional, regardless of the screen dimensions.</p>
<h3 id="heading-content-prioritization">Content Prioritization</h3>
<p>With breakpoints, designers can prioritize and reorganize content based on device capabilities and user needs. This ensures that essential information remains accessible and prominent, enhancing usability and engagement.</p>
<h3 id="heading-performance-optimization">Performance Optimization</h3>
<p>Breakpoints make websites load faster and work better on different devices by adjusting how they look and work based on each device's size and type. This is crucial for retaining user interest and reducing bounce rates, particularly on mobile devices with slower internet connections.</p>
<h3 id="heading-seo-friendliness">SEO Friendliness</h3>
<p>Responsive websites with well-implemented breakpoints provide a seamless user experience across devices. Search engines value responsive design because it improves accessibility and usability, potentially leading to better search engine rankings.</p>
<h2 id="heading-common-breakpoint-ranges-for-responsive-design-2024">Common Breakpoint Ranges for Responsive Design (2024)</h2>
<p>In 2024, responsive web design commonly employs a mobile-first approach, ensuring websites are designed to function and look good on smaller screens before scaling up. </p>
<p>Here are the typical breakpoint ranges used for different screen sizes:</p>
<p><strong>Extra Small Screens (Mobile):</strong></p>
<ul>
<li>Range: Up to 576px viewport width</li>
<li>Description: Targets smartphones and small mobile devices in portrait mode.</li>
</ul>
<p><strong>Small Screens (Tablets):</strong></p>
<ul>
<li>Range: 577px to 768px viewport width</li>
<li>Description: Includes larger smartphones and smaller tablets in portrait mode.</li>
</ul>
<p><strong>Medium Screens (Large Tablets):</strong></p>
<ul>
<li>Range: 769px to 1024px viewport width</li>
<li>Description: Targets larger tablets and smaller desktop screens in landscape mode.</li>
</ul>
<p><strong>Large Screens (Desktops):</strong></p>
<ul>
<li>Range: 1025px to 1440px viewport width</li>
<li>Description: Targets standard desktop screens and larger laptops.</li>
</ul>
<p><strong>Extra Large Screens (Large Desktops):</strong></p>
<ul>
<li>Range: 1441px and above viewport width</li>
<li>Description: Includes large desktop monitors and wide-screen displays.</li>
</ul>
<h3 id="heading-example-css-media-queries">Example CSS Media Queries:</h3>
<pre><code class="lang-css"><span class="hljs-comment">/* Example of CSS media queries for common breakpoint ranges */</span>

<span class="hljs-comment">/* Extra Small Screens (Mobile) */</span>
<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">576px</span>) {
  <span class="hljs-comment">/* CSS rules specific for extra small screens */</span>
  <span class="hljs-selector-class">.container</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; <span class="hljs-comment">/* Adjust layout for full-width on small screens */</span>
  }
}

<span class="hljs-comment">/* Small Screens (Tablets) */</span>
<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">577px</span>) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">768px</span>) {
  <span class="hljs-comment">/* CSS rules specific for small screens */</span>
  <span class="hljs-selector-class">.container</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>; <span class="hljs-comment">/* Adjust layout for smaller container width on tablets */</span>
  }
}

<span class="hljs-comment">/* Medium Screens (Large Tablets) */</span>
<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">769px</span>) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">1024px</span>) {
  <span class="hljs-comment">/* CSS rules specific for medium screens */</span>
  <span class="hljs-selector-class">.container</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">70%</span>; <span class="hljs-comment">/* Adjust layout for moderate container width on large tablets */</span>
  }
}

<span class="hljs-comment">/* Large Screens (Desktops) */</span>
<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">1025px</span>) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">1440px</span>) {
  <span class="hljs-comment">/* CSS rules specific for large screens */</span>
  <span class="hljs-selector-class">.container</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">60%</span>; <span class="hljs-comment">/* Adjust layout for narrower container width on desktops */</span>
  }
}

<span class="hljs-comment">/* Extra Large Screens (Large Desktops) */</span>
<span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">1441px</span>) {
  <span class="hljs-comment">/* CSS rules specific for extra large screens */</span>
  <span class="hljs-selector-class">.container</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">50%</span>; <span class="hljs-comment">/* Adjust layout for even narrower container width on large desktops */</span>
  }
}
</code></pre>
<p>In this example:</p>
<ul>
<li>Each media query targets a specific range of viewport widths to adjust the layout and styling of the <code>.container</code> element accordingly.</li>
<li>The percentages used for <code>width</code> in the examples demonstrate how designers can progressively adjust content presentation to optimize user experience across various devices and screen sizes.</li>
</ul>
<h2 id="heading-factors-to-consider-when-choosing-the-right-breakpoints-for-your-project">Factors to Consider When Choosing the Right Breakpoints for Your Project</h2>
<p>Choosing the right breakpoints for your project involves considering several factors:</p>
<h3 id="heading-target-audience-and-devices">Target Audience and Devices</h3>
<p>Understand the devices your target audience uses. This includes screen sizes of smartphones, tablets, laptops, and desktops. Prioritize breakpoints that align with these devices to ensure a seamless user experience.</p>
<h3 id="heading-content-complexity">Content Complexity</h3>
<p>Evaluate how your content responds to different screen sizes. Complex layouts may require additional breakpoints to maintain readability and usability across devices.</p>
<h3 id="heading-design-requirements">Design Requirements</h3>
<p>Your design specifications play an important role. Consider breakpoints that accommodate specific design elements such as navigation menus, images, forms, and grids. Ensure that these elements adapt well to different screen sizes.</p>
<h3 id="heading-analyzing-device-usage-statistics">Analyzing Device Usage Statistics</h3>
<p>Use analytics to determine the most common screen sizes among your audience. Focus on breakpoints that optimize user experience on these prevalent devices.</p>
<h2 id="heading-basic-structure-of-a-media-query">Basic Structure of a Media Query</h2>
<p>Implementing breakpoints with media queries is essential for creating responsive web designs that adapt to different screen sizes and devices. </p>
<p>A media query allows you to apply CSS styles based on certain conditions, such as screen width, height, device orientation, etc. The basic syntax of a media query is:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> media-type <span class="hljs-keyword">and</span> (media-feature) {
  <span class="hljs-comment">/* CSS styles */</span>
}
</code></pre>
<p>Where:</p>
<ul>
<li><code>media-type</code> specifies the type of media, typically <code>screen</code> for devices with screens.</li>
<li><code>media-feature</code> defines the condition, such as <code>width</code>, <code>min-width</code>, <code>max-width</code>, <code>orientation</code>, and so on.</li>
</ul>
<p>Now let's talk about how you can structure and use media queries effectively.</p>
<h3 id="heading-using-min-width-and-max-width-for-breakpoints">Using min-width and max-width for Breakpoints</h3>
<p>The most common approach to defining breakpoints is using <code>min-width</code> and <code>max-width</code> media features.</p>
<p><strong><code>min-width</code></strong>: Specifies the minimum width at which the styles should apply. It targets screens wider than the specified width.</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">min-width:</span> <span class="hljs-number">768px</span>) {
  <span class="hljs-comment">/* Styles for screens wider than 768px */</span>
}
</code></pre>
<p><strong><code>max-width</code></strong>: Specifies the maximum width at which the styles should apply. It targets screens narrower than the specified width.</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">1024px</span>) {
  <span class="hljs-comment">/* Styles for screens narrower than or equal to 1024px */</span>
}
</code></pre>
<h3 id="heading-media-queries-for-different-breakpoint-ranges">Media Queries for Different Breakpoint Ranges</h3>
<p>To create a responsive design that adapts to various devices, you typically define multiple breakpoints to cover different screen sizes:</p>
<h4 id="heading-small-screens-mobile-phones">Small Screens (Mobile Phones):</h4>
<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">576px</span>) {
  <span class="hljs-comment">/* Styles for small screens */</span>
}
</code></pre>
<h4 id="heading-medium-screens-tablets">Medium Screens (Tablets):</h4>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">577px</span>) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">992px</span>) {
  <span class="hljs-comment">/* Styles for medium screens */</span>
}
</code></pre>
<h4 id="heading-large-screens-desktops-and-laptops">Large Screens (Desktops and Laptops):</h4>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">993px</span>) {
  <span class="hljs-comment">/* Styles for large screens */</span>
}
</code></pre>
<h4 id="heading-extra-large-screens-large-desktops-and-monitors">Extra Large Screens (Large Desktops and Monitors):</h4>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">1200px</span>) {
  <span class="hljs-comment">/* Styles for extra large screens */</span>
}
</code></pre>
<h3 id="heading-example-comprehensive-media-queries">Example: Comprehensive Media Queries</h3>
<p>Here’s an example of how you might implement media queries for a responsive layout:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Default styles for all screens */</span>
<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
}

<span class="hljs-comment">/* Small screens (phones) */</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">576px</span>) {
  <span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  }
}

<span class="hljs-comment">/* Medium screens (tablets) */</span>
<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">577px</span>) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">992px</span>) {
  <span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
  }
}

<span class="hljs-comment">/* Large screens (desktops and laptops) */</span>
<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">993px</span>) {
  <span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
  }
}

<span class="hljs-comment">/* Extra large screens (large desktops and monitors) */</span>
<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">1200px</span>) {
  <span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;
  }
}
</code></pre>
<p>In this example:</p>
<ul>
<li>Font sizes adjust based on the screen size to ensure readability and optimal user experience.</li>
<li>Each media query targets specific ranges of screen widths using <code>min-width</code> and <code>max-width</code>.</li>
<li>Adjustments in font size are used here for demonstration purposes, but you can apply any CSS styles needed for your design.</li>
</ul>
<h2 id="heading-advanced-breakpoint-techniques">Advanced Breakpoint Techniques</h2>
<p>Implementing advanced breakpoint techniques enhances the responsiveness and adaptability of your web designs. </p>
<p>Here are several techniques you can use:</p>
<h3 id="heading-1-container-queries-adapting-to-content-width">1. Container Queries (Adapting to Content Width)</h3>
<p><strong>Container queries</strong> allow elements to respond not to the viewport size but to their own container's dimensions. This is particularly useful when you want elements to adapt based on their parent container's width rather than the overall screen width.</p>
<p>Example using a hypothetical container query syntax (not currently natively supported, but evolving in standards like CSS Houdini):</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-comment">/* Apply styles based on container width */</span>
}

<span class="hljs-keyword">@container</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">600px</span>) {
  <span class="hljs-selector-class">.container</span> {
    <span class="hljs-comment">/* Adjust styles for containers wider than 600px */</span>
  }
}
</code></pre>
<p>Container queries are highly anticipated as they provide more granular control over responsive design within individual components or sections.</p>
<h3 id="heading-2-flexible-units-ems-rems-for-responsive-layouts">2. Flexible Units (ems, rems) for Responsive Layouts</h3>
<p><strong>Flexible units</strong> like <code>em</code> (relative to the font-size of the element) and <code>rem</code> (relative to the font-size of the root element) are essential for creating scalable and responsive layouts.</p>
<h4 id="heading-using-em-and-rem">Using em and rem:</h4>
<ul>
<li><code>em</code> units scale relative to their parent element's font size. This can be useful for creating modular designs where elements resize proportionally.</li>
<li><code>rem</code> units are relative to the root element (<code>html</code>), providing a consistent base for scaling across the entire document.</li>
</ul>
<pre><code class="lang-css"><span class="hljs-comment">/* Example using rem for scalable font sizes */</span>
<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>; <span class="hljs-comment">/* Base font size */</span>
}

<span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>; <span class="hljs-comment">/* 32px on 16px base */</span>
}

<span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.5rem</span>; <span class="hljs-comment">/* 24px on 16px base */</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">768px</span>) {
  <span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>; <span class="hljs-comment">/* Adjust base font size for smaller screens */</span>
  }
}
</code></pre>
<h3 id="heading-3-using-css-grid-and-flexbox-for-responsive-design">3. Using CSS Grid and Flexbox for Responsive Design</h3>
<p><strong>CSS Grid</strong> and <strong>Flexbox</strong> are powerful layout tools that offer flexible and responsive design options.</p>
<p><strong>CSS Grid</strong>: Ideal for two-dimensional layouts, allowing precise control over rows and columns. Grids can adapt to different screen sizes with media queries or grid-auto-flow properties.</p>
<p>Example of responsive grid 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-built_in">repeat</span>(auto-fit, minmax(<span class="hljs-number">250px</span>, <span class="hljs-number">1</span>fr));
  <span class="hljs-attribute">grid-gap</span>: <span class="hljs-number">20px</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">768px</span>) {
  <span class="hljs-selector-class">.container</span> {
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr;
  }
}
</code></pre>
<p><strong>Flexbox</strong>: Best for simpler one-dimensional layouts or aligning items within a container. It’s great for navigation bars, sidebars, and elements within a grid cell.</p>
<p>Example of responsive Flexbox layout:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: space-between;
}

<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">768px</span>) {
  <span class="hljs-selector-class">.container</span> {
    <span class="hljs-attribute">flex-direction</span>: column;
  }
}
</code></pre>
<ul>
<li><strong>Container Queries</strong> are evolving and promise more precise control over responsive design elements based on their container's size.</li>
<li><strong>Flexible Units</strong> (<code>em</code>, <code>rem</code>) allow scalable and accessible typography and layout proportions across various screen sizes.</li>
<li><strong>CSS Grid</strong> and <strong>Flexbox</strong> provide robust layout options for creating responsive designs that adapt to different devices and viewport sizes.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, breakpoints play a pivotal role in crafting a responsive web design that adapts seamlessly across different devices and screen sizes. </p>
<p>The flexibility offered by media queries, utilizing <code>min-width</code> and <code>max-width</code> to define breakpoints, allows for precise control over how content and layouts respond to varying viewport dimensions. </p>
<p>Advanced techniques like container queries (as they evolve), flexible units (<code>em</code>, <code>rem</code>), and leveraging CSS Grid and Flexbox further enhance the adaptability and scalability of designs.</p>
<p>In essence, breakpoints are not just technical specifications but critical decisions that impact user interaction and satisfaction. </p>
<p>Connect with me on <a target="_blank" href="https://www.linkedin.com/in/joanayebola">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Viewing Patterns in Your Website Designs ]]>
                </title>
                <description>
                    <![CDATA[ While going through a website or an application, people tend to take in the information displayed differently. You may notice that sometimes a person may miss information that others wouldn't miss. This may have happened to you before, as well. This ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-viewing-patterns-in-your-website-design/</link>
                <guid isPermaLink="false">66d03a30ab216b4115759499</guid>
                
                    <category>
                        <![CDATA[ Accessibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Faith Olohijere ]]>
                </dc:creator>
                <pubDate>Wed, 12 Jun 2024 14:33:18 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/pexels-ramilugot-5011944.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>While going through a website or an application, people tend to take in the information displayed differently. You may notice that sometimes a person may miss information that others wouldn't miss. This may have happened to you before, as well.</p>
<p>This is because everyone has a particular way they process information. In design, this is called viewing (or reading) patterns. As a designer, it's important to understand how your users (including potential ones) consume information, and how best to place the most crucial information so nobody misses it.</p>
<p>In this article, we'll talk about different viewing patterns, how to choose the best ones for your project, and we'll also see real-life examples of these patterns.</p>
<h3 id="heading-heres-what-well-cover">Here's what we'll cover:</h3>
<ol>
<li>What you need to know before reading</li>
<li>The origin of viewing patterns</li>
<li>Common viewing patterns</li>
<li>Why are viewing patterns important?</li>
<li>How should I choose a viewing pattern for my design project?</li>
<li>Conclusion</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites:</h2>
<p>Before we go into the article proper, please note that it'll be helpful if you have basic knowledge of core design principles and the importance of these principles in guiding users' attention and organizing information effectively. </p>
<p>But this is not necessary, as I wrote this article for everyone, including absolute beginners.</p>
<h2 id="heading-the-origin-of-viewing-patterns">The Origin of Viewing Patterns</h2>
<p>The concept of viewing patterns can be traced to the field of psychology, specifically the study of eye movements and visual perception. </p>
<p>While people have been reading and consuming visual information for a long time, proper observation and analysis of reading behaviors emerged with the development of eye-tracking technology and scientific research methodologies in the late 19th and early 20th centuries.</p>
<p>A lot of pioneers and researchers such as Louis Emile Javal, Edmund Huey, Alfred L. Yarbus, and Charles H. Judd conducted experiments to observe eye movemts and behaviours in the late 19th century and early to mid-20th century.</p>
<p>The formalization of viewing/reading patterns as design principles in the context of graphic design and information architecture began to gain traction in the latter half of the 20th century. Designers and usability experts started applying insights from eye-tracking studies to optimize layouts for print media, signage, and digital interfaces.</p>
<p>Over time, the study of viewing patterns expanded beyond text-based reading to include diverse media formats, such as web pages, multimedia presentations, and interactive interfaces. </p>
<p>Today, viewing patterns continue to evolve with advancements in technology and changes in user behaviors, guiding the way designers approach layout, navigation, and content presentation.</p>
<h2 id="heading-common-viewing-patterns">Common Viewing Patterns</h2>
<p>Now that we know how viewing patterns came about, let's talk about some common viewing patterns in existence.</p>
<h3 id="heading-the-f-pattern">The F-pattern</h3>
<p>This is a common viewing pattern observed in online content consumption. According to this pattern, users scan the page in a horizontal movement across the top, then move down the page, scanning shorter horizontal sections. They continue to read less of the content, until they finally start reading vertically, forming the F-shape.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-56.png" alt="Image" width="600" height="400" loading="lazy">
<em>Diagram illustrating how the F-pattern works on a wireframe. Image Credit: <a target="_blank" href="https://www.nngroup.com/articles/f-shaped-pattern-reading-web-content/">Nielsen Norman Group</a></em></p>
<p>To capitalize on the F-pattern, you can place important information such as headlines, key points, and CTAs along the top and the left-hand side of the page to ensure maximum visibility. </p>
<p>Some examples of real-life platforms that utilize the F-pattern include:</p>
<ul>
<li><a target="_blank" href="https://shopify.com/">Shopify</a></li>
<li><a target="_blank" href="https://linkedin.com/">LinkedIn</a></li>
<li><a target="_blank" href="https://www.nytimes.com/">The New York Times</a></li>
</ul>
<h3 id="heading-the-z-pattern">The Z-Pattern</h3>
<p>The Z-pattern is another common viewing pattern. This pattern can be noticed in designs where the user is expected to move their eyes in a zig-zag pattern across the page. </p>
<p>This pattern typically starts with a horizontal movement across the top of the page (forming the first stroke of the "Z"), followed by a diagonal movement from the top-right to the bottom-left (forming the second stroke), and finally, another horizontal movement across the bottom of the page (completing the "Z"). </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Z-pattern.png" alt="Image" width="600" height="400" loading="lazy">
<em>Diagram illustrating the Z-pattern. Image Credit: <a target="_blank" href="https://uxplanet.org/z-shaped-pattern-for-reading-web-content-ce1135f92f1c">UX Planet</a></em></p>
<p>To capitalize on this pattern, you can align information on the predicted path of the Z-pattern to guide users' attention more effectively, especially in designs like landing pages and presentations.</p>
<p>Some examples of real-life platforms that utilize the Z-pattern include:</p>
<ul>
<li><a target="_blank" href="https://artykul.org/https://artykul.org/">Artykul</a></li>
<li><a target="_blank" href="https://www.mohash.co/">Mohash</a></li>
<li><a target="_blank" href="https://desclimbing.com/">Des Climbing</a></li>
</ul>
<h3 id="heading-the-gutenberg-diagram">The Gutenberg Diagram</h3>
<p>The Gutenberg diagram outlines a viewing pattern based on the natural eye movement of Western readers, and is influenced by cultural and linguistic factors. </p>
<p>The Gutenberg Diagram divides the page into four quadrants: the primary optical area (top-left), the strong fallow area (top-right), the weak fallow area (bottom-left), and the terminal area (bottom-right).</p>
<blockquote>
<p>The pattern suggests that the eye will sweep across and down the page in a series of horizontal movements called axes of orientation. Each sweep starts a little further from the left edge and moves a little closer to the right edge. The overall movement is for the eye to travel from the primary area to the terminal area... – Stephen Bradley (<a target="_blank" href="https://vanseodesign.com/web-design/3-design-layouts/">Vanseo Design</a>)</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-1--3-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image illustrating Gutenberg diagram divided into 4 quadrants. Image Credit: <a target="_blank" href="https://www.techwala.in/gutenberg-diagram-why-you-should-know-it-and-use-it/">Techwala</a></em></p>
<p>You can strategically place content based on the Gutenberg diagram to optimize visual hierarchy and readability, ensuring that important information receives the most attention.</p>
<p>Some examples of real-life platforms that utilize the Gutenberg diagram include:</p>
<ul>
<li><a target="_blank" href="http://www.wikipedia.org/">Wikipedia</a></li>
<li><a target="_blank" href="http://www.bbc.com/news">BBC News</a></li>
</ul>
<h3 id="heading-layer-cake-pattern">Layer-Cake Pattern</h3>
<p>The layer-cake pattern involves stacking multiple layers of content vertically, with each layer containing distinct information or visual elements.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-3--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image illustrating the layer-cake pattern on a layout. Image Credit: <a target="_blank" href="https://chipcullen.com/layer-cake-design-pattern/">Chip Cullen</a></em></p>
<p>Users typically engage with this pattern by scanning the top layer first, then sequentially exploring deeper layers based on their interest or curiosity. You can use this pattern to present complex information in a more structured format, allowing users to navigate through layers of content at their own pace.</p>
<p>Some examples of real-life platforms that utilize the Layer-Cake pattern include:</p>
<ul>
<li><a target="_blank" href="http://www.medium.com/">Medium</a></li>
<li><a target="_blank" href="http://www.squarespace.com/">Squarespace</a></li>
</ul>
<h2 id="heading-why-are-viewing-patterns-important">Why are Viewing Patterns Important?</h2>
<p>Viewing patterns help you guide how users view and consume information on your designs. They help you arrange content in a way that naturally aligns with your users' reading habits. By placing information where users are most likely to look first, you're ensuring that key messages are effectively communicated. </p>
<p>Also, understanding viewing patterns help you cater to the needs of a diverse group of users. Different people process information in different ways and understanding these habits ensure that you design with accessibility in mind.</p>
<p>What's more, designs that align with existing viewing patterns provide a more intuitive and less stressful user experience. </p>
<h2 id="heading-how-should-i-choose-a-viewing-pattern-for-my-design-project">How Should I Choose a Viewing Pattern for my Design Project?</h2>
<p>Choosing a viewing pattern for your design depends on a number of factors including, the context of your project, users' preferences, goals of the project, and so on. </p>
<p>Here's a step-by-step guide to help you select the best reading pattern for your project:</p>
<ol>
<li>Know your Users: You have to first understand the demographics of your target or potential users. What do they prefer? What are their goals? In what situations would they use your project? Gather insights into how they interact with content and their technical proficiency.</li>
<li>Define your Project Goals: Make sure to clarify the objectives and desired outcomes of the project you're working on. Are you trying to inform or facilitate a specific action? Should your design be very serious or a little playful? You need to identify the key messages you want to pass across to your users, and prioritize them based on importance. </li>
<li>Evaluate Context and Platform: Take into account how your users would view your product. Will they view your content on a website, application or a print medium? Consider the device types and screen sizes that your users are likely to use.</li>
<li>Select Viewing Pattern: Considering the available data and the insights you've gathered, you can go ahead to choose a viewing pattern that best aligns with your project objectives. </li>
</ol>
<p>Now that you've selected a viewing pattern for your design, make sure to constantly monitor it's effectiveness through testing and feedback.</p>
<p>Note: You can interchange these steps or even skip some. Just make sure to do whatever works best for your users.</p>
<h3 id="heading-lets-do-a-little-practical-exercise">Let's do a little practical exercise:</h3>
<p>Say you're working on a hero section for a new e-commerce website selling outdoor gear. Some things you need to consider for this project include:</p>
<ul>
<li>The primary goal: to showcase the latest product offerings on the hero section and entice visitors to visit the website further. You'll want to highlight key features, products, and calls-to-action (CTAs) to encourage conversion such as making a purchase or signing up for a newsletter.</li>
<li>Your target users: likely outdoor enthusiasts, including hikers, campers, and adventure seekers. They'll likely be people with limited time to spend on each webpage.</li>
<li>Context and platform: Users will likely access the page on several devices, including desktop computers, laptops, tablets, and smartphones. You'll want to consider how the design will adapt responsively across different screen sizes and orientations, priortizing mobile optimization for on-the-go users.</li>
</ul>
<p>Due to the time constraints of your users, and the need to capture attention quickly, the F-pattern may be a suitable choice. Place high-priority content, such as featured products, top deals, and prominent CTAs, along the top and left-hand side of the page, where users are most likely to look first. </p>
<p>You can use visual cues such as arrows, bold typography, and contrasting colors to draw attention to key elements and guide users' eye movements down the page.</p>
<p>Here's what I came up with from the practical design:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Frame-19-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Hero section I designed using the F-pattern.</em></p>
<p>In the design above, in sequential order, there's:</p>
<ul>
<li>a top navigation containing the logo, links to other sub-pages, and the log-in and sign up CTAs(call-to-actions).</li>
<li>a main heading, description, and call-to-action (Shop Now) on the left-hand side of the page.</li>
<li>a section showing latest arrivals on the website.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Frame-20--3--1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image showing how the F-pattern is depicted on the design.</em></p>
<p>I would love to see the results of this practical exercise on your end.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Viewing patterns are very important as I mentioned earlier. They are invaluable for designers across different disciplines, and are easy to understand and incorporate into your designs. </p>
<p>You just need to be sure of what works best for your users, and design with that in mind. Also make sure to experiment with different viewing patterns so you can discover your own unique style. Have fun experimenting!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Login Page with the Material Tailwind Framework – Step by Step Guide ]]>
                </title>
                <description>
                    <![CDATA[ Login pages are like the front doors to our web apps. They should be inviting, easy to use, and safe. If you're looking to create one that combines both style and function, you're in the right place. In this guide, we'll explore how to build a login ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-login-page-with-material-tailwind-framework/</link>
                <guid isPermaLink="false">66c375a9b737bb2ce7073268</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tailwind ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Alexandru Paduraru ]]>
                </dc:creator>
                <pubDate>Mon, 29 Apr 2024 14:21:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/how-to-build-a-login-page-with-the-material-tailwind-framework-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Login pages are like the front doors to our web apps. They should be inviting, easy to use, and safe. If you're looking to create one that combines both style and function, you're in the right place.</p>
<p>In this guide, we'll explore how to build a login page with <a href="https://material-tailwind.com/" target="_blank">Material Tailwind</a> and Tailwind CSS that not only looks great but also works seamlessly across devices. </p>
<p>Whether you're new to web design or just curious about these tools, we'll walk you through each step. Let's dive in and start building! </p>
<p>Happy coding 🤘🏼</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<p>Check out the article chapters:</p>
<ol>
<li><a class="post-section-overview" href="#heading-1-introduction-to-tailwind-css-and-material-tailwind">Introduction to Tailwind CSS and Material Tailwind</a> </li>
<li><a class="post-section-overview" href="#heading-2-how-to-set-up-your-development-environment">How to Set Up Your Development Environment</a> </li>
<li><a class="post-section-overview" href="#heading-3-how-to-install-necessary-dependencies-for-your-login-page">How to Install Necessary Dependencies for your Login Page</a> </li>
<li><a class="post-section-overview" href="#heading-4-how-to-design-the-login-page-layout-with-tailwind-css">How to Design the Layout with Tailwind CSS</a>  </li>
<li><a class="post-section-overview" href="#heading-5-how-to-integrate-material-tailwind-components">How to Integrate Material Tailwind Components</a> </li>
<li><a class="post-section-overview" href="#heading-6-how-to-style-input-fields-and-buttons">How to Style Input Fields and Buttons</a>  </li>
<li><a class="post-section-overview" href="#heading-7-how-to-implement-responsive-design">How to Implement Responsive Design</a>  </li>
<li><a class="post-section-overview" href="#heading-8-how-to-add-interactivity-and-validation">How to Add Interactivity and Validation</a></li>
<li><a class="post-section-overview" href="#heading-9-security-and-best-practices-for-login-pages">Security and Best Practices for Login Pages</a> </li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusions</a> </li>
</ol>
<h2 id="heading-1-introduction-to-tailwind-css-and-material-tailwind">1. Introduction to Tailwind CSS and Material Tailwind</h2>
<p>Web design has many tools to help make good-looking and easy-to-use websites. </p>
<p>Two useful tools are <a href="https://tailwindcss.com/" target="_blank">Tailwind CSS</a> and <a href="https://material-tailwind.com/" target="_blank">Material Tailwind</a>. Tailwind CSS helps web designers make websites quickly without writing a lot of extra code. Material Tailwind adds nice-looking designs that are easy to change. Together, they can help you make a <a href="https://www.material-tailwind.com/blocks/authentication" target="_blank">Tailwind CSS login page</a> that looks good and works well. </p>
<p>In this section, you can see more details about these tools and why they're useful.</p>
<h3 id="heading-what-is-tailwind-css">What is <a href="https://tailwindcss.com/" target="_blank">Tailwind CSS</a>?</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/tailwind-css.jpg" alt="tailwind css" width="600" height="400" loading="lazy">
<em>Tailwind CSS homepage</em></p>
<p>Tailwind is a utility-first CSS framework. Instead of pre-designed components, it provides low-level utility classes that let you build custom designs without leaving your HTML. </p>
<p>Since its launch, Tailwind CSS has taken the web development community by storm. By 2023, the framework had gained over <a href="https://github.com/tailwindlabs/tailwindcss" target="_blank">400 million downloads on Github</a>, a proof of its growing adoption among developers. Several popular companies and platforms also started adopting Tailwind, for example: <a href="https://vercel.com/" target="_blank">Vercel</a>, <a href="https://www.algolia.com/" target="_blank">Algolia</a>, <a href="https://www.netlify.com/" target="_blank">Netlify</a>, and others. The Github statistics show over 74,000 stars, which indicates a strong community backing. </p>
<p><strong>Why use Tailwind CSS:</strong></p>
<ul>
<li>Speed: Quickly build UIs with utility classes instead of writing custom CSS.</li>
<li>Flexibility: You can customize designs without restrictions.</li>
<li>Responsiveness: Easily make designs that work on all device sizes.</li>
</ul>
<p>Example: Instead of writing custom CSS for a button, use utility classes directly in your HTML.</p>
<pre><code>&lt;button <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"</span>&gt;
   View More
&lt;/button&gt;
</code></pre><h3 id="heading-what-is-material-tailwind">What is <a href="https://material-tailwind.com/" target="_blank">Material Tailwind</a>?</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/material-tailwind.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Material Tailwind homepage</em></p>
<p>Material Tailwind is a components library for Tailwind CSS that implements Google's Material Design guidelines. It combines the best of both worlds: the utility-first approach of Tailwind and the design philosophy of Material Design.</p>
<p><strong>Why use Material Tailwind:</strong></p>
<ul>
<li>Consistency: Follows Material Design guidelines, ensuring familiar <a href="https://www.material-tailwind.com/roots-of-ui-ux-design" target="_blank">UI/UX patterns</a>.</li>
<li>Customizable: Being built on Tailwind, it's highly customizable.</li>
<li>Component-rich: Comes with pre-built components that speed up development.</li>
</ul>
<p>Example: Imagine you want a Material Design inspired <a href="https://www.material-tailwind.com/docs/react/button" target="_blank">button</a>. With Material Tailwind, it's straightforward.</p>
<pre><code>&lt;button
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"middle none center rounded-lg bg-pink-500 py-3 px-6 font-sans text-xs font-bold uppercase text-white shadow-md shadow-pink-500/20 transition-all hover:shadow-lg hover:shadow-pink-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  data-ripple-light=<span class="hljs-string">"true"</span>
&gt;
  View More
&lt;/button&gt;
</code></pre><p>If you are a React fan too, let me tell you that Material Tailwind also comes with Tailwind CSS + React components. For more details, check out the <a href="https://www.material-tailwind.com/docs/react/installation" target="_blank">Material Tailwind React documentation</a>.</p>
<p>Now let’s see how you can use these two amazing tools to create your desired Login Page.</p>
<h2 id="heading-2-how-to-set-up-your-development-environment">2. How to Set Up Your Development Environment</h2>
<p>Creating a development environment tailored for your web project ensures smooth and efficient workflow. For our <a href="https://www.material-tailwind.com/docs/html/card#login-card" target="_blank">Tailwind CSS login page</a>, we’ll start from scratch.</p>
<p>Prerequisites:</p>
<ul>
<li>Node.js and npm (Node Package Manager): These are essential for installing and managing libraries we’ll be using.</li>
<li>A Text Editor or IDE: While any text editor will work, Visual Studio Code (VS Code) is recommended due to its extensive library of extensions beneficial for web development.</li>
<li>Terminal or Command Prompt: We'll be running commands to set up and manage our project.</li>
</ul>
<h3 id="heading-install-nodejs-and-npm">Install Node.js and npm</h3>
<p>To start, visit the <a href="https://nodejs.org/" target="_blank">Node.js official website</a> and download the recommended version for your OS.</p>
<p>After installation, verify that Node.js and npm are correctly installed by running the following commands:</p>
<pre><code>node -v
npm -v
</code></pre><h3 id="heading-set-up-a-new-project">Set up a new project</h3>
<p>Create a new directory for your project:</p>
<pre><code>mkdir tailwind-material-login
cd tailwind-material-login
</code></pre><p>Then initialize a new npm project:</p>
<pre><code>npm init -y
</code></pre><h3 id="heading-text-editoride-setup-vs-code">Text Editor/IDE Setup (VS Code)</h3>
<p>If you haven’t already, download and install <a href="https://code.visualstudio.com/" target="_blank">VS Code</a>. Then go ahead and open your project directory in VS Code.</p>
<p>Optionally, you can install extensions that enhance Tailwind CSS development:</p>
<ul>
<li>Tailwind CSS IntelliSense: Offers class name autocompletions, linting, and more.</li>
<li>Live Server: Allows you to see live changes without manually refreshing the browser.</li>
</ul>
<h3 id="heading-terminal-in-vs-code">Terminal in VS Code</h3>
<p>VS Code offers an integrated terminal. This means you can run commands directly within your editor.</p>
<p>To open it, go to the top menu: View &gt; Terminal or press Ctrl + a backtick.</p>
<h3 id="heading-basic-project-structure">Basic Project Structure</h3>
<p>Create a basic structure for your project:</p>
<pre><code>mkdir src
touch src/index.html
touch src/styles.css
touch src/main.js
</code></pre><p>This creates a src directory with an HTML file, a CSS file, and a JavaScript file.</p>
<h2 id="heading-3-how-to-install-necessary-dependencies-for-your-login-page">3. How to Install Necessary Dependencies for your Login Page</h2>
<p>Setting up your libraries and frameworks is crucial to build upon a solid foundation. For our Tailwind CSS login page, we'll be primarily using Tailwind CSS and Material Tailwind. </p>
<p>Here’s a step-by-step guide to installing and configuring these dependencies.</p>
<h3 id="heading-how-to-install-tailwind-css">How to install Tailwind CSS</h3>
<p>First, you'll need to install the Tailwind CSS package. Using npm, install the Tailwind CSS package with:</p>
<pre><code>npm install tailwindcss
</code></pre><p>Then, integrate Tailwind into your CSS. Inside your src/styles.css file, add the following Tailwind directives:</p>
<pre><code>@<span class="hljs-keyword">import</span> <span class="hljs-string">'tailwindcss/base'</span>;
@<span class="hljs-keyword">import</span> <span class="hljs-string">'tailwindcss/components'</span>;
@<span class="hljs-keyword">import</span> <span class="hljs-string">'tailwindcss/utilities'</span>;
</code></pre><p>Next, you'll need to generate a configuration file. While Tailwind works out of the box, a configuration file (tailwind.config.js) provides customization capabilities. </p>
<p>To generate it:</p>
<pre><code>npx tailwindcss init
</code></pre><p>This creates a minimal config file in your root directory. You can extend this file as needed.</p>
<p>Finally, to process your CSS and apply Tailwind’s transformations, add a script in your package.json under the "scripts" section:</p>
<pre><code><span class="hljs-string">"scripts"</span>: {
<span class="hljs-string">"build-css"</span>: <span class="hljs-string">"tailwind build src/styles.css -o src/output.css"</span>
}
</code></pre><p>Run the script with:</p>
<pre><code>npm run build-css
</code></pre><p>This will generate an output.css containing all Tailwind's styles. Include this file in your HTML.</p>
<h3 id="heading-how-to-install-material-tailwind">How to install Material Tailwind</h3>
<p>First, install the Material Tailwind package. Again, you can use npm:</p>
<pre><code>npm i @material-tailwind/html
</code></pre><p>Now you need to integrate it into your project. Material Tailwind provides components with styles applied. You can use them directly in your HTML or customize them further in your CSS.</p>
<p>For instance, to use a Material Tailwind button:</p>
<pre><code>&lt;button
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"middle none center rounded-lg bg-pink-500 py-3 px-6 font-sans text-xs font-bold uppercase text-white shadow-md shadow-pink-500/20 transition-all hover:shadow-lg hover:shadow-pink-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  data-ripple-light=<span class="hljs-string">"true"</span>
&gt;
  View More
&lt;/button&gt;
</code></pre><p>Next, install the required fonts and icons. Material Design recommends specific fonts and icons. Include these in your <code>src/index.html</code>:</p>
<pre><code>&lt;!-- Material Icons Link --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/icon?family=Material+Icons"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>/&gt;</span></span> 

&lt;!-- Font Awesome Link --&gt;
<span class="xml"><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">href</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha512-HK5fgLBL+xu6dm/Ii3z4xhlSUyZgTT9tuc/hSrtw6uzJOvgRr2a9jyxxT1ely+B+xFAmJKVSTbpM/CuL7qxO8w=="</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>/&gt;</span></span>
</code></pre><h3 id="heading-postcss-and-autoprefixer-recommended">PostCSS and Autoprefixer (Recommended)</h3>
<p>Install PostCSS and Autoprefixer:</p>
<pre><code>npm install postcss postcss-cli autoprefixer
</code></pre><p>Go ahead and configure them by creating a postcss.config.js in your root directory:</p>
<pre><code><span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">plugins</span>: [
    <span class="hljs-built_in">require</span>(<span class="hljs-string">'tailwindcss'</span>),
    <span class="hljs-built_in">require</span>(<span class="hljs-string">'autoprefixer'</span>),
  ]
};
</code></pre><p>Modify your build-css script in package.json to:</p>
<pre><code><span class="hljs-string">"build-css"</span>: <span class="hljs-string">"postcss src/styles.css -o src/output.css"</span>
</code></pre><p>This ensures your Tailwind CSS styles are vendor-prefixed, making them compatible across different browsers.</p>
<p>Add into your project’s <code>&lt;head&gt;</code> the output.css styling file.</p>
<pre><code>&lt;link rel=<span class="hljs-string">"stylesheet"</span> href=<span class="hljs-string">"pathTo/output.css"</span> /&gt;
</code></pre><h2 id="heading-4-how-to-design-the-login-page-layout-with-tailwind-css">4. How to Design the Login Page Layout with Tailwind CSS</h2>
<p>A <a href="https://www.material-tailwind.com/docs/html/card#login-card" target="_blank">login page</a> typically consists of a logo or branding, input fields (like username and password), a submit button, and often some secondary options or links, such as "Forgot Password" or "Sign Up".</p>
<h3 id="heading-main-container">Main Container:</h3>
<p>Start with a main container that centers its content both vertically and horizontally.</p>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"min-h-screen flex items-center justify-center bg-gray-100"</span>&gt;
&lt;!-- Login Card Content Will Go Here --&gt;
&lt;/div&gt;
</code></pre><h3 id="heading-login-card">Login Card:</h3>
<p>Create a centered card layout that will house the login form. Introduce the necessary input fields for the login process, typically an email/username and password.</p>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"relative flex flex-col text-gray-700 bg-white shadow-md w-96 rounded-xl bg-clip-border"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"relative grid mx-4 mb-4 -mt-6 overflow-hidden text-white shadow-lg h-28 place-items-center rounded-xl bg-gradient-to-tr from-gray-900 to-gray-800 bg-clip-border shadow-gray-900/20"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block font-sans text-3xl antialiased font-semibold leading-snug tracking-normal text-white"</span>&gt;</span>
      Sign In
    <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex flex-col gap-4 p-6"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"relative h-11 w-full min-w-[200px]"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full h-full px-3 py-3 font-sans text-sm font-normal transition-all bg-transparent border rounded-md peer border-blue-gray-200 border-t-transparent text-blue-gray-700 outline outline-0 placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:border-2 focus:border-gray-900 focus:border-t-transparent focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[' '] after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none !overflow-visible truncate text-[11px] font-normal leading-tight text-gray-500 transition-all before:pointer-events-none before:mt-[6.5px] before:mr-1 before:box-border before:block before:h-1.5 before:w-2.5 before:rounded-tl-md before:border-t before:border-l before:border-blue-gray-200 before:transition-all after:pointer-events-none after:mt-[6.5px] after:ml-1 after:box-border after:block after:h-1.5 after:w-2.5 after:flex-grow after:rounded-tr-md after:border-t after:border-r after:border-blue-gray-200 after:transition-all peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[4.1] peer-placeholder-shown:text-blue-gray-500 peer-placeholder-shown:before:border-transparent peer-placeholder-shown:after:border-transparent peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-gray-900 peer-focus:before:border-t-2 peer-focus:before:border-l-2 peer-focus:before:!border-gray-900 peer-focus:after:border-t-2 peer-focus:after:border-r-2 peer-focus:after:!border-gray-900 peer-disabled:text-transparent peer-disabled:before:border-transparent peer-disabled:after:border-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
        Email
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</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">class</span>=<span class="hljs-string">"relative h-11 w-full min-w-[200px]"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full h-full px-3 py-3 font-sans text-sm font-normal transition-all bg-transparent border rounded-md peer border-blue-gray-200 border-t-transparent text-blue-gray-700 outline outline-0 placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:border-2 focus:border-gray-900 focus:border-t-transparent focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[' '] after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none !overflow-visible truncate text-[11px] font-normal leading-tight text-gray-500 transition-all before:pointer-events-none before:mt-[6.5px] before:mr-1 before:box-border before:block before:h-1.5 before:w-2.5 before:rounded-tl-md before:border-t before:border-l before:border-blue-gray-200 before:transition-all after:pointer-events-none after:mt-[6.5px] after:ml-1 after:box-border after:block after:h-1.5 after:w-2.5 after:flex-grow after:rounded-tr-md after:border-t after:border-r after:border-blue-gray-200 after:transition-all peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[4.1] peer-placeholder-shown:text-blue-gray-500 peer-placeholder-shown:before:border-transparent peer-placeholder-shown:after:border-transparent peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-gray-900 peer-focus:before:border-t-2 peer-focus:before:border-l-2 peer-focus:before:!border-gray-900 peer-focus:after:border-t-2 peer-focus:after:border-r-2 peer-focus:after:!border-gray-900 peer-disabled:text-transparent peer-disabled:before:border-transparent peer-disabled:after:border-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
        Password
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</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">class</span>=<span class="hljs-string">"-ml-2.5"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"inline-flex items-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"checkbox"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"relative flex items-center p-3 rounded-full cursor-pointer"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>
            <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[''] peer relative h-5 w-5 cursor-pointer appearance-none rounded-md border border-blue-gray-200 transition-all before:absolute before:top-2/4 before:left-2/4 before:block before:h-12 before:w-12 before:-translate-y-2/4 before:-translate-x-2/4 before:rounded-full before:bg-blue-gray-500 before:opacity-0 before:transition-opacity checked:border-gray-900 checked:bg-gray-900 checked:before:bg-gray-900 hover:before:opacity-10"</span>
            <span class="hljs-attr">id</span>=<span class="hljs-string">"checkbox"</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>
            <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute text-white transition-opacity opacity-0 pointer-events-none top-2/4 left-2/4 -translate-y-2/4 -translate-x-2/4 peer-checked:opacity-100"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h-3.5 w-3.5"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 20 20"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"currentColor"</span>
              <span class="hljs-attr">stroke</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"1"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">"evenodd"</span>
                <span class="hljs-attr">d</span>=<span class="hljs-string">"M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"</span>
                <span class="hljs-attr">clip-rule</span>=<span class="hljs-string">"evenodd"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-px font-light text-gray-700 cursor-pointer select-none"</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"checkbox"</span>&gt;</span>
          Remember Me
        <span class="hljs-tag">&lt;/<span class="hljs-name">label</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>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p-6 pt-0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"block w-full select-none rounded-lg bg-gradient-to-tr from-gray-900 to-gray-800 py-3 px-6 text-center align-middle font-sans text-xs font-bold uppercase text-white shadow-md shadow-gray-900/10 transition-all hover:shadow-lg hover:shadow-gray-900/20 active:opacity-[0.85] disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
      <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span>&gt;</span>
      Sign In
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex justify-center mt-6 font-sans text-sm antialiased font-light leading-normal text-inherit"</span>&gt;</span>
      Don't have an account?
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#signup"</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">"block ml-1 font-sans text-sm antialiased font-bold leading-normal text-blue-gray-900"</span>&gt;</span>
        Sign up
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <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>
&lt;/div&gt;
</code></pre><h3 id="heading-login-button">Login Button:</h3>
<p>Place the primary action button (Login) below the input fields.</p>
<pre><code>&lt;button
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"block w-full select-none rounded-lg bg-gradient-to-tr from-gray-900 to-gray-800 py-3 px-6 text-center align-middle font-sans text-xs font-bold uppercase text-white shadow-md shadow-gray-900/10 transition-all hover:shadow-lg hover:shadow-gray-900/20 active:opacity-[0.85] disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  type=<span class="hljs-string">"button"</span>&gt;
  Sign In
&lt;/button&gt;
</code></pre><h3 id="heading-secondary-options">Secondary Options:</h3>
<p>Beneath the login button, offer options such as "Forgot Password" or "Sign Up".</p>
<h2 id="heading-5-how-to-integrate-material-tailwind-components">5. How to Integrate Material Tailwind Components</h2>
<p>Material Design, initiated by Google, is a design system that combines classic principles of good design with innovative technologies. When fused with the utility-first approach of Tailwind CSS via <a href="https://www.material-tailwind.com" target="_blank">Material Tailwind</a>, it provides a powerful toolkit to create interactive and visually appealing user interfaces.</p>
<p>Material Tailwind provides styled components that adhere to Material Design guidelines but harness the utility of Tailwind. This means that while most of the styling is pre-configured, you can still utilize Tailwind classes for customization.</p>
<ul>
<li><strong><a href="https://www.material-tailwind.com/docs/html/input" target="_blank">Input Fields</a></strong></li>
</ul>
<p>Instead of the standard Tailwind-styled inputs, you can introduce Material-styled input fields for a more tactile and animated experience:</p>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"relative h-10 w-full min-w-[200px]"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"peer h-full w-full rounded-[7px] border border-blue-gray-200 border-t-transparent bg-transparent px-3 py-2.5 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:border-2 focus:border-pink-500 focus:border-t-transparent focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
  /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[' '] after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none text-[11px] font-normal leading-tight text-blue-gray-400 transition-all before:pointer-events-none before:mt-[6.5px] before:mr-1 before:box-border before:block before:h-1.5 before:w-2.5 before:rounded-tl-md before:border-t before:border-l before:border-blue-gray-200 before:transition-all after:pointer-events-none after:mt-[6.5px] after:ml-1 after:box-border after:block after:h-1.5 after:w-2.5 after:flex-grow after:rounded-tr-md after:border-t after:border-r after:border-blue-gray-200 after:transition-all peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[3.75] peer-placeholder-shown:text-blue-gray-500 peer-placeholder-shown:before:border-transparent peer-placeholder-shown:after:border-transparent peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-pink-500 peer-focus:before:border-t-2 peer-focus:before:border-l-2 peer-focus:before:border-pink-500 peer-focus:after:border-t-2 peer-focus:after:border-r-2 peer-focus:after:border-pink-500 peer-disabled:text-transparent peer-disabled:before:border-transparent peer-disabled:after:border-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
    Email
  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span></span>
&lt;/div&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"relative h-10 w-full min-w-[200px]"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"peer h-full w-full rounded-[7px] border border-blue-gray-200 border-t-transparent bg-transparent px-3 py-2.5 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:border-2 focus:border-pink-500 focus:border-t-transparent focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
  /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[' '] after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none text-[11px] font-normal leading-tight text-blue-gray-400 transition-all before:pointer-events-none before:mt-[6.5px] before:mr-1 before:box-border before:block before:h-1.5 before:w-2.5 before:rounded-tl-md before:border-t before:border-l before:border-blue-gray-200 before:transition-all after:pointer-events-none after:mt-[6.5px] after:ml-1 after:box-border after:block after:h-1.5 after:w-2.5 after:flex-grow after:rounded-tr-md after:border-t after:border-r after:border-blue-gray-200 after:transition-all peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[3.75] peer-placeholder-shown:text-blue-gray-500 peer-placeholder-shown:before:border-transparent peer-placeholder-shown:after:border-transparent peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-pink-500 peer-focus:before:border-t-2 peer-focus:before:border-l-2 peer-focus:before:border-pink-500 peer-focus:after:border-t-2 peer-focus:after:border-r-2 peer-focus:after:border-pink-500 peer-disabled:text-transparent peer-disabled:before:border-transparent peer-disabled:after:border-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
    Password
  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre><p>These components offer a floating label effect and subtle focus animations out of the box.</p>
<ul>
<li><strong><a href="https://www.material-tailwind.com/docs/html/button" target="_blank">Buttons</a></strong></li>
</ul>
<p>Material Tailwind offers a set of button styles that fit within the Material Design paradigm:</p>
<pre><code>&lt;button
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"middle none center rounded-lg bg-pink-500 py-3 px-6 font-sans text-xs font-bold uppercase text-white shadow-md shadow-pink-500/20 transition-all hover:shadow-lg hover:shadow-pink-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  data-ripple-light=<span class="hljs-string">"true"</span>
&gt;
  Login
&lt;/button&gt;
</code></pre><p>This renders a raised button with Material's signature ripple effect on click.</p>
<ul>
<li><strong><a href="https://www.material-tailwind.com/docs/html/tooltip" target="_blank">Tooltips</a></strong></li>
</ul>
<p>To enhance user guidance, you can add tooltips to your components:</p>
<pre><code>&lt;button
  data-ripple-light=<span class="hljs-string">"true"</span>
  data-tooltip-target=<span class="hljs-string">"tooltip"</span>
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"middle none center rounded-lg bg-gradient-to-tr from-pink-600 to-pink-400 py-3 px-6 font-sans text-xs font-bold uppercase text-white shadow-md shadow-pink-500/20 transition-all hover:shadow-lg hover:shadow-pink-500/40 active:opacity-[0.85] disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
&gt;
  Show Tooltip
&lt;/button&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
  <span class="hljs-attr">data-tooltip</span>=<span class="hljs-string">"tooltip"</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute z-50 whitespace-normal break-words rounded-lg bg-black py-1.5 px-3 font-sans text-sm font-normal text-white focus:outline-none"</span>
&gt;</span>
  Login Form
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre><p>When users hover over the element, they'll see a tooltip providing additional information.</p>
<ul>
<li><strong>Incorporating <a href="https://www.material-tailwind.com/docs/html/icon-button" target="_blank">Material Icons</a></strong></li>
</ul>
<p>Material Design also has a rich set of icons. Material Tailwind makes it easy to incorporate these:</p>
<pre><code>&lt;button
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"item-center middle none center flex justify-center rounded-lg bg-pink-500 p-3 font-sans text-xs font-bold uppercase text-white shadow-md shadow-pink-500/20 transition-all hover:shadow-lg hover:shadow-pink-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  data-ripple-light=<span class="hljs-string">"true"</span>
&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fas fa-heart text-lg leading-none"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span></span>
&lt;/button&gt;
</code></pre><p>Make sure you've already linked to Material icons in your HTML as instructed earlier.</p>
<ul>
<li><strong><a href="https://www.material-tailwind.com/docs/html/theming" target="_blank">Customizing Material Components</a></strong></li>
</ul>
<p>While Material Tailwind components come pre-styled, you can still leverage Tailwind utility classes for customizations:</p>
<pre><code>&lt;button 
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"button button-pink !bg-blue-500 px-4"</span> 
  data-ripple-light=<span class="hljs-string">"true"</span>
&gt;
  Button
&lt;/button&gt;
</code></pre><p>Here, we've overridden the default primary color with a custom shade of purple from Tailwind's color palette.</p>
<p>Incorporating Material Tailwind components provides an elegant touch to the login page, combining the efficiency of Tailwind CSS with the visual and interactive richness of Material Design. The result is a responsive, user-friendly, and visually cohesive login experience. </p>
<p>Also, you can check the components library’s <a href="https://www.material-tailwind.com/blocks/authentication" target="_blank">Tailwind CSS login page templates</a>.</p>
<h2 id="heading-6-how-to-style-input-fields-and-buttons">6. How to Style Input Fields and Buttons</h2>
<p>The appearance and feel of input fields and buttons play a pivotal role in user experience. They're the primary interaction points. Let's focus on giving them a sleek, user-friendly design using Material Tailwind and Tailwind CSS.</p>
<ol>
<li><strong><a href="https://www.material-tailwind.com/docs/html/input" target="_blank">Material Tailwind Input Fields</a>:</strong></li>
</ol>
<p>Material Tailwind offers a more polished look for input fields out of the box. Here's how you can integrate them:</p>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"relative h-11 w-full min-w-[200px]"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"peer h-full w-full border-b border-blue-gray-200 bg-transparent pt-4 pb-1.5 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border-blue-gray-200 focus:border-pink-500 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
  /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none text-[11px] font-normal leading-tight text-blue-gray-500 transition-all after:absolute after:-bottom-1.5 after:block after:w-full after:scale-x-0 after:border-b-2 after:border-pink-500 after:transition-transform after:duration-300 peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[4.25] peer-placeholder-shown:text-blue-gray-500 peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-pink-500 peer-focus:after:scale-x-100 peer-focus:after:border-pink-500 peer-disabled:text-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
    Email
  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span></span>
&lt;/div&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"relative h-11 w-full min-w-[200px]"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"peer h-full w-full border-b border-blue-gray-200 bg-transparent pt-4 pb-1.5 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border-blue-gray-200 focus:border-pink-500 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
  /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none text-[11px] font-normal leading-tight text-blue-gray-500 transition-all after:absolute after:-bottom-1.5 after:block after:w-full after:scale-x-0 after:border-b-2 after:border-pink-500 after:transition-transform after:duration-300 peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[4.25] peer-placeholder-shown:text-blue-gray-500 peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-pink-500 peer-focus:after:scale-x-100 peer-focus:after:border-pink-500 peer-disabled:text-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
    Password
  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre><p>These fields come with improved focus effects and an overall refined look, making them more engaging.</p>
<ol start="2">
<li><strong><a href="https://www.material-tailwind.com/docs/html/icon-button" target="_blank">Enhancing with Icons</a>:</strong></li>
</ol>
<p>Integrating Material icons can guide users and enhance visual cues:</p>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"relative h-10 w-full min-w-[200px]"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute top-2/4 right-3 grid h-5 w-5 -translate-y-2/4 place-items-center text-blue-gray-500"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fas fa-heart"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"peer h-full w-full rounded-[7px] border border-blue-gray-200 border-t-transparent bg-transparent px-3 py-2.5 !pr-9 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:border-2 focus:border-pink-500 focus:border-t-transparent focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span>
  /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[' '] after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none text-[11px] font-normal leading-tight text-blue-gray-400 transition-all before:pointer-events-none before:mt-[6.5px] before:mr-1 before:box-border before:block before:h-1.5 before:w-2.5 before:rounded-tl-md before:border-t before:border-l before:border-blue-gray-200 before:transition-all after:pointer-events-none after:mt-[6.5px] after:ml-1 after:box-border after:block after:h-1.5 after:w-2.5 after:flex-grow after:rounded-tr-md after:border-t after:border-r after:border-blue-gray-200 after:transition-all peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[3.75] peer-placeholder-shown:text-blue-gray-500 peer-placeholder-shown:before:border-transparent peer-placeholder-shown:after:border-transparent peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-pink-500 peer-focus:before:border-t-2 peer-focus:before:border-l-2 peer-focus:before:border-pink-500 peer-focus:after:border-t-2 peer-focus:after:border-r-2 peer-focus:after:border-pink-500 peer-disabled:text-transparent peer-disabled:before:border-transparent peer-disabled:after:border-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
    Input With Icon
  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span></span>
&lt;/div&gt;
</code></pre><p>The email field now includes a mail icon on the left, giving users a clear indication of the input type.</p>
<ol start="3">
<li><strong><a href="https://www.material-tailwind.com/docs/html/button" target="_blank">Material Tailwind Buttons</a>:</strong></li>
</ol>
<p>Material Tailwind buttons come pre-styled with Material aesthetics. However, you can further customize their appearance with Tailwind utility classes:</p>
<pre><code>&lt;button
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"middle none center rounded-lg bg-pink-500 py-3 px-6 font-sans text-xs font-bold uppercase text-white shadow-md shadow-pink-500/20 transition-all hover:shadow-lg hover:shadow-pink-500/40 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  data-ripple-light=<span class="hljs-string">"true"</span>
&gt;
  Login
&lt;/button&gt;
</code></pre><p>In this example, the button has a primary blue background color with different shades on hover and active states.</p>
<ol start="4">
<li><strong><a href="https://www.material-tailwind.com/docs/html/button" target="_blank">Button Variations</a>:</strong></li>
</ol>
<p>Offering secondary or tertiary actions? You can use outlined or text buttons:</p>
<ul>
<li>Gradient Button:</li>
</ul>
<pre><code>&lt;button
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"middle none center mr-3 rounded-lg bg-gradient-to-tr from-pink-600 to-pink-400 py-3 px-6 font-sans text-xs font-bold uppercase text-white shadow-md shadow-pink-500/20 transition-all hover:shadow-lg hover:shadow-pink-500/40 active:opacity-[0.85] disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  data-ripple-light=<span class="hljs-string">"true"</span>
&gt;
  Gradient Button
&lt;/button&gt;
</code></pre><ul>
<li>Outlined Button:</li>
</ul>
<pre><code>&lt;button
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"middle none center mr-3 rounded-lg border border-pink-500 py-3 px-6 font-sans text-xs font-bold uppercase text-pink-500 transition-all hover:opacity-75 focus:ring focus:ring-pink-200 active:opacity-[0.85] disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  data-ripple-dark=<span class="hljs-string">"true"</span>
&gt;
  Outlined Button
&lt;/button&gt;
</code></pre><ul>
<li>Text Button:</li>
</ul>
<pre><code>&lt;button
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"middle none center rounded-lg py-3 px-6 font-sans text-xs font-bold uppercase text-pink-500 transition-all hover:bg-pink-500/10 active:bg-pink-500/30 disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  data-ripple-dark=<span class="hljs-string">"true"</span>
&gt;
  Text Button
&lt;/button&gt;
</code></pre><ol start="5">
<li><strong>Responsiveness and Sizing:</strong></li>
</ol>
<p>Remember to consider different device sizes. Tailwind's responsive utilities can help:</p>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"relative h-10 w-full md:w-50 lg:w-24"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"peer h-full w-full rounded-[7px] border border-blue-gray-200 border-t-transparent bg-transparent px-3 py-2.5 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:border-2 focus:border-pink-500 focus:border-t-transparent focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
  /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[' '] after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none text-[11px] font-normal leading-tight text-blue-gray-400 transition-all before:pointer-events-none before:mt-[6.5px] before:mr-1 before:box-border before:block before:h-1.5 before:w-2.5 before:rounded-tl-md before:border-t before:border-l before:border-blue-gray-200 before:transition-all after:pointer-events-none after:mt-[6.5px] after:ml-1 after:box-border after:block after:h-1.5 after:w-2.5 after:flex-grow after:rounded-tr-md after:border-t after:border-r after:border-blue-gray-200 after:transition-all peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[3.75] peer-placeholder-shown:text-blue-gray-500 peer-placeholder-shown:before:border-transparent peer-placeholder-shown:after:border-transparent peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-pink-500 peer-focus:before:border-t-2 peer-focus:before:border-l-2 peer-focus:before:border-pink-500 peer-focus:after:border-t-2 peer-focus:after:border-r-2 peer-focus:after:border-pink-500 peer-disabled:text-transparent peer-disabled:before:border-transparent peer-disabled:after:border-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
    Required
  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span></span>
&lt;/div&gt;
</code></pre><p>This input field takes the full width on smaller screens, but only half the width on larger ones.</p>
<h2 id="heading-7-how-to-implement-responsive-design">7. How to Implement Responsive Design</h2>
<p>A significant strength of Tailwind CSS lies in its mobile-first approach to responsive design. Ensuring your login page looks good and functions well on all devices is crucial for user experience.</p>
<p>Tailwind CSS is built with a mobile-first mindset. This means that by default, the classes you apply are for mobile views. To target larger screens, you utilize breakpoints. For instance:</p>
<pre><code>.text-sm md:text-base lg:text-xl
</code></pre><p>On mobile, the text size would be sm, on medium-sized screens (like tablets) it would be base, and on large screens (like desktops) it would be xl.</p>
<ul>
<li>Responsive Card Layout: While our login card may look great on desktop, it might be too narrow on mobile. You can adjust this:</li>
</ul>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"relative flex flex-col text-gray-700 bg-white shadow-md w-96 rounded-xl bg-clip-border"</span>&gt;
&lt;!-- Login Content --&gt;
&lt;/div&gt;
</code></pre><p>Here, we're using less padding (p-4) and taking full width (w-full) on mobile, but increasing the padding (md:p-8) and setting a fixed width (md:w-96) on medium screens and above.</p>
<ul>
<li>Adapting Input Fields and Buttons: Ensure that interactive elements are easily accessible on touch devices:</li>
</ul>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"relative h-10 w-full mb-4 md:mb-0"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"peer h-full w-full rounded-[7px] border border-blue-gray-200 border-t-transparent bg-transparent px-3 py-2.5 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:border-2 focus:border-pink-500 focus:border-t-transparent focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
  /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[' '] after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none text-[11px] font-normal leading-tight text-blue-gray-400 transition-all before:pointer-events-none before:mt-[6.5px] before:mr-1 before:box-border before:block before:h-1.5 before:w-2.5 before:rounded-tl-md before:border-t before:border-l before:border-blue-gray-200 before:transition-all after:pointer-events-none after:mt-[6.5px] after:ml-1 after:box-border after:block after:h-1.5 after:w-2.5 after:flex-grow after:rounded-tr-md after:border-t after:border-r after:border-blue-gray-200 after:transition-all peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[3.75] peer-placeholder-shown:text-blue-gray-500 peer-placeholder-shown:before:border-transparent peer-placeholder-shown:after:border-transparent peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-pink-500 peer-focus:before:border-t-2 peer-focus:before:border-l-2 peer-focus:before:border-pink-500 peer-focus:after:border-t-2 peer-focus:after:border-r-2 peer-focus:after:border-pink-500 peer-disabled:text-transparent peer-disabled:before:border-transparent peer-disabled:after:border-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
    Email
  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span></span>
&lt;/div&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"middle none center mr-3 rounded-lg border border-pink-500 py-3 px-6 font-sans text-xs font-bold uppercase text-pink-500 transition-all hover:opacity-75 focus:ring focus:ring-pink-200 active:opacity-[0.85] disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
  <span class="hljs-attr">data-ripple-dark</span>=<span class="hljs-string">"true"</span>
&gt;</span>
  Login
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre><p>On mobile, the input fields and buttons take up the full width for easier touch access but adapt to more spacious designs on larger screens.</p>
<ul>
<li>Handling Landscape Mode: Sometimes, especially on mobile devices, landscape mode can drastically alter layouts. Consider adding specific styles for this using Tailwind's landscape plugin (if you've added it to your configuration):</li>
</ul>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"mt-10 landscape:mt-4"</span>&gt;
&lt;!-- Login Content --&gt;
&lt;/div&gt;
</code></pre><p>In landscape mode, the top margin is reduced to accommodate the shorter viewport height.</p>
<ul>
<li><a href="https://www.material-tailwind.com/docs/html/typography" target="_blank">Typography</a> Adjustments: Optimal readability is essential. Ensure text sizes are appropriate for various devices:</li>
</ul>
<pre><code>&lt;h2 
  <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"block font-sans text-4xl font-semibold leading-[1.3] tracking-normal text-inherit antialiased"</span>
&gt;
  Sign In to Your Account
&lt;/h2&gt;
</code></pre><p>On mobile, the title is slightly smaller, but it scales up on medium and larger screens.</p>
<ul>
<li>Testing Responsiveness:  While Tailwind offers the tools to create responsive designs, always test your layouts on actual devices or using browser tools. This ensures a consistent experience across devices and resolutions.</li>
</ul>
<h2 id="heading-8-how-to-add-interactivity-and-validation">8. How to Add Interactivity and Validation</h2>
<p>A successful login page isn't just about looks – it must provide feedback, handle user input gracefully, and validate that input to ensure security and functionality.</p>
<p>Material Tailwind components come with built-in animations and feedback mechanisms. For instance, when you click a Material Tailwind button, you'll see a ripple effect, providing immediate feedback to the user.</p>
<h3 id="heading-toggle-password-visibility">Toggle Password Visibility:</h3>
<p>A common feature in login forms is the ability to toggle password visibility. This improves user experience, especially on mobile devices where typing mistakes are more frequent. Using Material icons and some simple JavaScript:</p>
<pre><code>
&lt;form id=<span class="hljs-string">"loginForm"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"relative mb-4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"relative h-10 w-full min-w-[200px]"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute top-2/4 right-3 grid h-5 w-5 -translate-y-2/4 place-items-center text-blue-gray-500"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fas fa-heart"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</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">input</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">"peer h-full w-full rounded-[7px] border border-blue-gray-200 border-t-transparent bg-transparent px-3 py-2.5 !pr-9 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:border-2 focus:border-pink-500 focus:border-t-transparent focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
        <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>
      /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[' '] after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none text-[11px] font-normal leading-tight text-blue-gray-400 transition-all before:pointer-events-none before:mt-[6.5px] before:mr-1 before:box-border before:block before:h-1.5 before:w-2.5 before:rounded-tl-md before:border-t before:border-l before:border-blue-gray-200 before:transition-all after:pointer-events-none after:mt-[6.5px] after:ml-1 after:box-border after:block after:h-1.5 after:w-2.5 after:flex-grow after:rounded-tr-md after:border-t after:border-r after:border-blue-gray-200 after:transition-all peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[3.75] peer-placeholder-shown:text-blue-gray-500 peer-placeholder-shown:before:border-transparent peer-placeholder-shown:after:border-transparent peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-pink-500 peer-focus:before:border-t-2 peer-focus:before:border-l-2 peer-focus:before:border-pink-500 peer-focus:after:border-t-2 peer-focus:after:border-r-2 peer-focus:after:border-pink-500 peer-disabled:text-transparent peer-disabled:before:border-transparent peer-disabled:after:border-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
      Password
      <span class="hljs-tag">&lt;/<span class="hljs-name">label</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">button</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"middle none center mr-3 rounded-lg border border-pink-500 py-3 px-6 font-sans text-xs font-bold uppercase text-pink-500 transition-all hover:opacity-75 focus:ring focus:ring-pink-200 active:opacity-[0.85] disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"</span>
      <span class="hljs-attr">data-ripple-dark</span>=<span class="hljs-string">"true"</span>
      <span class="hljs-attr">id</span>=<span class="hljs-string">"togglePassword"</span>
    &gt;</span>
      Submit
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/form&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">const</span> passwordField = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'password'</span>);
    <span class="hljs-keyword">const</span> togglePasswordBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'togglePassword'</span>);

    togglePasswordBtn.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">if</span> (passwordField.type === <span class="hljs-string">"password"</span>) {
            passwordField.type = <span class="hljs-string">"text"</span>;
        } <span class="hljs-keyword">else</span> {
            passwordField.type = <span class="hljs-string">"password"</span>;
        }
    });
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre><p>Clicking the visibility icon will now toggle the password field between visible and obscured states.</p>
<h3 id="heading-client-side-validation">Client-Side Validation:</h3>
<p>While never a replacement for server-side validation, client-side validation provides immediate feedback:</p>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"relative h-10 w-full min-w-[200px]"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute top-2/4 right-3 grid h-5 w-5 -translate-y-2/4 place-items-center text-blue-gray-500"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fas fa-heart"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"peer h-full w-full rounded-[7px] border border-blue-gray-200 border-t-transparent bg-transparent px-3 py-2.5 !pr-9 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:border-2 focus:border-pink-500 focus:border-t-transparent focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"</span>
    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">" "</span>
    <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
    <span class="hljs-attr">required</span>
    <span class="hljs-attr">pattern</span>=<span class="hljs-string">"[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$"</span>
  /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"before:content[' '] after:content[' '] pointer-events-none absolute left-0 -top-1.5 flex h-full w-full select-none text-[11px] font-normal leading-tight text-blue-gray-400 transition-all before:pointer-events-none before:mt-[6.5px] before:mr-1 before:box-border before:block before:h-1.5 before:w-2.5 before:rounded-tl-md before:border-t before:border-l before:border-blue-gray-200 before:transition-all after:pointer-events-none after:mt-[6.5px] after:ml-1 after:box-border after:block after:h-1.5 after:w-2.5 after:flex-grow after:rounded-tr-md after:border-t after:border-r after:border-blue-gray-200 after:transition-all peer-placeholder-shown:text-sm peer-placeholder-shown:leading-[3.75] peer-placeholder-shown:text-blue-gray-500 peer-placeholder-shown:before:border-transparent peer-placeholder-shown:after:border-transparent peer-focus:text-[11px] peer-focus:leading-tight peer-focus:text-pink-500 peer-focus:before:border-t-2 peer-focus:before:border-l-2 peer-focus:before:border-pink-500 peer-focus:after:border-t-2 peer-focus:after:border-r-2 peer-focus:after:border-pink-500 peer-disabled:text-transparent peer-disabled:before:border-transparent peer-disabled:after:border-transparent peer-disabled:peer-placeholder-shown:text-blue-gray-500"</span>&gt;</span>
  Email
  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span></span>
&lt;/div&gt;
</code></pre><p>The required attribute ensures the field is not left empty, and the pattern attribute uses a basic regex to validate email structure.</p>
<h3 id="heading-handling-form-submission">Handling Form Submission:</h3>
<p>When the user attempts to log in, you can provide feedback using JavaScript:</p>
<pre><code><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'loginForm'</span>).addEventListener(<span class="hljs-string">'submit'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{
    event.preventDefault();

    <span class="hljs-comment">// Fetch input values</span>
    <span class="hljs-keyword">const</span> email = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'email'</span>).value;
    <span class="hljs-keyword">const</span> password = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'password'</span>).value;

    <span class="hljs-comment">// Example: Check if credentials are empty</span>
    <span class="hljs-keyword">if</span> (!email || !password) {
        alert(<span class="hljs-string">'Please fill in all fields.'</span>);
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Handle actual submission to server</span>

    <span class="hljs-comment">// On success:</span>
    <span class="hljs-comment">// alert('Logged in successfully!');</span>

    <span class="hljs-comment">// On failure:</span>
    <span class="hljs-comment">// alert('Invalid credentials. Please try again.');</span>
});
</code></pre><p>The code above prevents the default form submission and provides feedback depending on the input. This is a simplistic approach, and in real-world scenarios, you'd interact with server endpoints to authenticate the user.</p>
<h3 id="heading-handling-errors-and-feedback">Handling Errors and Feedback:</h3>
<p>It's crucial to provide clear feedback in the event of errors or successful actions. Consider using modals, snack bars, or simple inline messages to communicate the status of actions to users.</p>
<p>For example, using Tailwind:</p>
<pre><code>&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"bg-red-500 text-white p-4 rounded-md mt-4"</span> id=<span class="hljs-string">"errorMessage"</span> style=<span class="hljs-string">"display: none;"</span>&gt;
Invalid credentials. Please <span class="hljs-keyword">try</span> again.
&lt;/div&gt;
</code></pre><p>Then, using JavaScript, you can show or hide this error message based on the authentication result.</p>
<h2 id="heading-9-security-and-best-practices-for-login-pages">9. Security and Best Practices for Login Pages</h2>
<p>Security is paramount when dealing with user authentication. A well-designed login page not only enhances user experience but also acts as the first line of defense against potential threats.</p>
<h3 id="heading-https-and-encryption">HTTPS and Encryption:</h3>
<p>Before any other consideration, ensure your website uses HTTPS. This encrypts data transmitted between the user's browser and your server, protecting it from eavesdropping and tampering.</p>
<h3 id="heading-password-security">Password Security:</h3>
<p>Client-Side:</p>
<ul>
<li>Never store passwords in plain text or local storage.</li>
<li>Use password input fields (type="password") to hide password characters.</li>
</ul>
<p>Server-Side:</p>
<ul>
<li>Always hash and salt passwords before storing them in your database.</li>
<li>Consider using proven libraries like bcrypt for hashing.</li>
</ul>
<h3 id="heading-avoid-verbose-error-messages">Avoid Verbose Error Messages:</h3>
<p>If authentication fails, avoid specifying whether it was the username or password that was incorrect. Instead, use generic messages:</p>
<pre><code>alert(<span class="hljs-string">'Invalid login credentials. Please try again.'</span>);
</code></pre><p>This prevents attackers from determining if a particular email or username is registered with your site.</p>
<ul>
<li><strong>Limit Login Attempts:</strong> Implement a system to track failed login attempts and consider locking out users or implementing CAPTCHAs after a certain threshold is reached. This helps prevent brute-force attacks.</li>
<li><strong>Implement CAPTCHAs:</strong> Tools like Google's reCAPTCHA can help ensure that login attempts are made by humans, not automated scripts. This further protects against brute-force and bot-driven attacks.</li>
<li><strong>Secure Password Reset</strong> - If you provide a "Forgot Password" option:<ul>
<li>Use one-time tokens that expire after a short duration.</li>
<li>Send the reset link to the registered email instead of allowing password changes directly from the login page.</li>
<li>Always ask security questions or verify user identity before allowing password resets.</li>
</ul>
</li>
<li><strong>Cross-Site Scripting (XSS) and SQL Injection</strong>: Always sanitize and validate input data to protect against XSS attacks and SQL injections. Utilize parameterized queries or prepared statements to prevent SQL injections.</li>
<li><strong>Keep Libraries and Dependencies Updated</strong>: Regularly update your server software, libraries, and other dependencies to ensure you're protected against known vulnerabilities.</li>
<li><strong>Use Content Security Policy (CSP)</strong>: A CSP helps prevent a wide range of attacks, including XSS. It limits the sources of executable scripts, ensuring that only trusted sources are allowed.</li>
<li><strong>Logging and Monitoring</strong>: Keep logs of authentication attempts, especially failed ones. Monitoring these can alert you to potential attacks or suspicious activities.</li>
<li><strong>Two-Factor Authentication (2FA)</strong>: Consider implementing 2FA for added user account protection. This requires users to provide two distinct forms of identification before gaining access.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Building a login page might seem easy, but there's a lot to think about. It should look good, work well, be easy to use on any device, and be safe. Thanks to tools like <a href="https://tailwindcss.com/" target="_blank">Tailwind CSS</a> and <a href="https://material-tailwind.com/" target="_blank">Material Tailwind</a>, you can make great login pages without too much hassle.</p>
<p>In this guide, we started from scratch and ended up with a ready-to-use login page. By combining Tailwind CSS's easy style tools and Material Design's nice looks, users get a great experience every time they log in.</p>
<p>But remember, technology keeps changing. So, always keep learning and updating your skills.</p>
<h3 id="heading-useful-links">Useful links:</h3>
<ul>
<li><a href="https://tailwindcss.com/" target="_blank">Tailwind CSS Website</a></li>
<li><a href="https://github.com/tailwindlabs/tailwindcss" target="_blank">Tailwind CSS Github</a></li>
<li><a href="https://material-tailwind.com/" target="_blank">Material Tailwind Website</a></li>
<li><a href="https://github.com/creativetimofficial/material-tailwind" target="_blank">Material Tailwind Github</a></li>
<li><a href="https://www.material-tailwind.com/docs/html/installation" target="_blank">Material Tailwind Documentation</a></li>
<li><a href="https://www.creative-tim.com/templates/tailwind" target="_blank">Free Tailwind CSS Website Templates</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Biophilic Design? How to Reconnect with Nature through Web Design ]]>
                </title>
                <description>
                    <![CDATA[ In a world where we're constantly glued to screens and distracted by digital noise, it's easy to forget about nature.  But here's the exciting part: biophilic design offers a cool solution. Usually, it's all about bringing nature into buildings, but ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-biophilic-design/</link>
                <guid isPermaLink="false">66bb89232108ff2ab9af166f</guid>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Jaja ]]>
                </dc:creator>
                <pubDate>Tue, 23 Apr 2024 18:28:38 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/Article-Cover-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In a world where we're constantly glued to screens and distracted by digital noise, it's easy to forget about nature. </p>
<p>But here's the exciting part: biophilic design offers a cool solution. Usually, it's all about bringing nature into buildings, but now nature is branching out into web design as well.</p>
<p>In this article, we'll explore why we feel disconnected from nature and how biophilic design can help fix that, even in the digital world.</p>
<h2 id="heading-what-is-biophilic-design">What is Biophilic Design?</h2>
<p>Well, it's all about bringing nature back into our lives, whether it's at home, in the office, or wherever we hang out. </p>
<p>It's not just about making things look pretty – it's about making us feel good by reconnecting us with the great outdoors.</p>
<h3 id="heading-history-of-biophilic-design">History of Biophilic Design</h3>
<p>Biophilic design, stemming from the Greek words "bios" (life) and "philia" (love), is all about our natural connection to the world around us. It has its roots in architecture and building design, where people realised that bringing elements of nature into our spaces makes us feel better.</p>
<p>This design approach mimics nature's patterns and includes views of trees and natural light. It's a way of making our homes and workplaces feel more like the outdoors.</p>
<p><img src="https://lh7-us.googleusercontent.com/AL3lORAbV4kKYN94RLG_GCBD3dH0OJtS6V5NtitRfCrPixCweHYZgdzSgwBeUykwhHwkAo-A7gkxCDCBU0uFGoOFleD-kvZ7YVaRvOd1SFT_3Y6SfYuG8bE0MP-W8p75r1stRhiZualfNKTlj_h-TC0" alt="Image" width="600" height="400" loading="lazy">
<em>Biophilic Design in Architecture</em></p>
<p>As cities grow and technology becomes more important, we spend less time in nature. That's why biophilic design is so important. It's not just for buildings – it's also being used in things like website design to remind us of our love for nature.</p>
<p>So, whether it's in a physical space or online, biophilic design helps us remember how much we need nature for our happiness and well-being.</p>
<h2 id="heading-the-problem-understanding-our-distance-from-nature">The Problem: Understanding Our Distance from Nature</h2>
<h3 id="heading-how-screens-shape-our-lives">How Screens Shape Our Lives</h3>
<p>You know how it is these days – screens are everywhere, right? From our smartphones and tablets to laptops and TVs, they've become like companions, keeping us hooked for hours. </p>
<p>Sometimes it feels like we're living in a whole different world, one that's all digital and disconnected from nature.</p>
<p>Ever found yourself mindlessly scrolling through social media or binge-watching shows, losing track of time? It's what some call "zombie-scrolling" – we've all been there. 😌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/Endless-Scrolling.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Endless Scrolling</em></p>
<h3 id="heading-lost-in-the-digital-world-wheres-nature">Lost in the Digital World: Where's Nature?</h3>
<p>We're all guilty of getting sucked into the digital vortex. Whether it's getting lost in Netflix marathons, being glued to our work screens or endless scrolling through Insta… (Let’s be serious, it’s Twitter 😂), our attention rarely strays from the virtual realm. And the more we dive into digital content, the further we drift from the great outdoors. </p>
<p>It's like we're building this invisible wall between ourselves and nature without even realizing it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/Tweet-it.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Tweet it</em></p>
<h3 id="heading-were-missing-out-on-natures-charms">We're Missing Out on Nature's Charms</h3>
<p>With our lives becoming more and more centered around screens, outdoor adventures seem to be a thing of the past. Many of us spend our days cooped up indoors, surrounded by artificial lights and controlled temperatures. It's like we've forgotten what it feels like <em>actually to touch grass</em> or feel the sun on our faces. There's just not much incentive to step outside and soak in the beauty of nature anymore.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/Touch-grass.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-but-were-often-unaware-of-the-disconnect">But We're Often Unaware of the Disconnect</h3>
<p>Here's the thing: Many of us don't even realize how far we've drifted from nature. We're so caught up in the digital world that we hardly think about how it's affecting us and our connection to nature. It's like this subtle but important change that sneaks up on us until we pause and reflect on it.</p>
<p>And here's the kicker: this disconnection isn't just about not enjoying nature's beauty. It's also messing with our health. </p>
<p><a target="_blank" href="https://www.who.int/news-room/fact-sheets/detail/physical-activity">Research shows</a> that spending too much time indoors and not enough time outdoors can cause issues like obesity, depression, and not getting enough vitamin D. Lack of physical activity is a big deal, contributing to millions of deaths every year worldwide. </p>
<p>So, while binge-watching shows or scrolling through social media all day might seem harmless, it's impacting our health and well-being in a big way.</p>
<h2 id="heading-the-harmful-effects-of-a-disconnect-from-nature">The Harmful Effects of a Disconnect from Nature</h2>
<p>As we've seen, our increasing immersion in the digital world comes with consequences beyond just missing out on the joys of nature. This disconnect has profound effects on our health and well-being, impacting us in ways we might not even realize.</p>
<ul>
<li><strong>Mental Health Struggles</strong>: Spending excessive time indoors and away from nature has been linked to higher rates of depression, anxiety, and stress. Without the calming influence of natural environments, our mental health can suffer, leaving us feeling more isolated and disconnected from the world around us.</li>
<li><strong>Physical Health Risks</strong>: Being too sedentary, especially with too much screen time, poses serious risks to our physical health. Conditions like obesity, cardiovascular disease, and diabetes are just some of the issues linked to not being active enough and spending too much time indoors. Our bodies thrive on movement and natural light, and depriving them of these essentials can take a toll on our health.</li>
<li><strong>Vitamin D Deficiency</strong>: Not getting enough sunlight indoors means missing out on vital nutrients like vitamin D, essential for bone health, immune function, and mood regulation. Without sufficient sunlight exposure, we become more prone to deficiencies that can affect our overall health in various ways.</li>
<li><strong>Disconnect from Reality</strong>: As we go deeper into the digital space, we risk losing touch with reality. This gradual disconnection from the natural world means we miss out on the sights, sounds, and sensations that keep us grounded. Ultimately, this disconnect can leave us feeling adrift and disconnected from both ourselves and the world around us.</li>
</ul>
<h2 id="heading-biophilic-elements-in-web-design">Biophilic Elements in Web Design</h2>
<p>Let's talk bout how you can incorporate bits of nature into your website design to help bring the outdoors in and reconnect with the natural world.</p>
<h3 id="heading-natural-forms-and-patterns">Natural Forms and Patterns</h3>
<p>Integrating organic shapes, textures, and patterns reminiscent of nature is key. In web design, this means crafting interfaces that mirror the fluidity and diversity of the natural world.</p>
<p>For example, the UI below utilizes a hanging flower pattern to represent a flower shop, embracing the beauty of nature in its design (<a target="_blank" href="https://dribbble.com/shots/17272076-Floristry-and-decor-studio-Website">reference</a>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/01-Floral-website-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Floral Website</em></p>
<h3 id="heading-natural-materials-and-textures">Natural Materials and Textures</h3>
<p>Incorporating natural materials and textures is crucial for creating a warm and inviting digital environment. Just like in physical spaces, using elements that mimic natural materials can evoke a sense of comfort and connection. </p>
<p>For instance, the UI below shapes the landing page of a woodworking company, resembling components of a furniture piece. This use of imagery mimics the texture and warmth of wood, enhancing the user experience and bringing the outdoors to your screen (<a target="_blank" href="https://dribbble.com/shots/18785612-Selling-decorative-wooden-home-products">reference</a>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/02-Wood-Website.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Woodworking Website</em></p>
<h3 id="heading-natural-light-and-views">Natural Light and Views</h3>
<p>Natural light is crucial in biophilic design for creating visually appealing spaces that promote well-being. Similarly, in web design, incorporating light and outdoor views enhances the user experience, fostering a sense of openness and connection to nature. </p>
<p>Maximizing natural light in web layouts involves creating airy designs with ample white space to let light in. Incorporating images or animations of outdoor scenes, like lush landscapes or serene water bodies, deepens the connection to nature, infusing websites with tranquillity and wonder. </p>
<p>For example, the UI below uses real images of nature to brighten up the webpage, harnessing natural light to enhance the user experience (r<a target="_blank" href="https://dribbble.com/shots/23220749-LeafLife-Garden-Landscape-Design-Website-UI-Figma-Template">eference</a>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/04-Landscape-website.png" alt="Image" width="600" height="400" loading="lazy">
<em>Landscape Website</em></p>
<h3 id="heading-biophilic-colors">Biophilic Colors</h3>
<p>Colours play a significant role in shaping the mood and user experience. Incorporating colours inspired by nature can cultivate a soothing atmosphere, reinforcing the connection between users and the natural world. </p>
<p>Choosing nature-inspired colours such as earth tones, greens, and blues evokes feelings of tranquillity, vitality, and serenity. These hues, commonly found in natural landscapes, can evoke positive emotions in users.</p>
<p>For instance, the UI below utilizes shades of green to convey a sense of freshness and health associated with the company's food offerings. This use of colour triggers positive associations with nature, enhancing the overall user experience (<a target="_blank" href="https://dribbble.com/shots/23951260-Gardening-Landscaping-website">reference</a>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/05-Vegitation-Website.png" alt="Image" width="600" height="400" loading="lazy">
<em>Vegetation Website</em></p>
<h3 id="heading-living-systems-and-biomimicry">Living Systems and Biomimicry</h3>
<p>Biomimicry, mimicking natural processes in design, provides rich inspiration for creating efficient, sustainable, and user-friendly solutions. This involves drawing from natural ecosystems to guide website functionality and navigation. </p>
<p>Emulating natural systems in website design can lead to intuitive user experiences that mirror the adaptability of the natural world. By studying living systems, designers can apply these principles to digital interfaces, enhancing usability and engagement.</p>
<p>For example, the UI below incorporates elements of human anatomy to communicate the company's purpose effectively. This biomimetic approach helps users intuitively understand the company's offerings, enhancing the overall user experience (<a target="_blank" href="https://dribbble.com/shots/20365657-The-Landing-Page-for-the-BioAge-Website">reference</a>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/06---Biomimicry-website.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Biomimicry Website</em></p>
<h2 id="heading-benefits-of-biophilic-web-design">Benefits of Biophilic Web Design</h2>
<p>Biophilic web design offers a multitude of benefits that extend beyond mere aesthetics.</p>
<ul>
<li><strong>Enhanced User Experience</strong>: Biophilic elements have the power to evoke positive emotions and create a more engaging user experience. Natural forms, colors, and textures can resonate with users on a subconscious level, fostering a sense of comfort, connection, and delight as they interact with the website.</li>
<li><strong>Improved Well-being</strong>: Exposure to nature, even in digital form, has been shown to reduce stress and enhance cognitive function. By immersing users in environments reminiscent of the natural world, biophilic web design can create digital spaces that promote relaxation, focus, and overall well-being.</li>
<li><strong>Differentiation and Brand Identity</strong>: Incorporating biophilic design can set a website apart from competitors and communicate values of sustainability and connection to the natural world. By aligning with themes of environmental stewardship and holistic living, brands can differentiate themselves and forge deeper connections with environmentally conscious consumers.</li>
<li><strong>Increased User Engagement</strong>:  When websites offer a visually appealing and calming experience, users are more inclined to stick around. By crafting digital environments that mirror the tranquillity and beauty of nature, designers can captivate users' attention, prompting them to explore, interact, and come back for more.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/Minion-Kiss.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Minion Kiss</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As we wrap up our exploration of biophilic design in web design, remember this: while screens can be captivating, don't forget to reconnect with nature. Biophilic design isn't just about aesthetics – it's about infusing digital spaces with the serenity of the outdoors.</p>
<p>And hey, here's a friendly question: Have you touched some grass today 😒? It might be just the digital detox your soul needs. Step away from the screen and immerse yourself in the beauty of the natural world. Your mind, body, and spirit will thank you.</p>
<h3 id="heading-contact-information">Contact Information</h3>
<p>Want to connect or contact me? Feel free to hit me up on the following:</p>
<ul>
<li>Twitter / X: <a target="_blank" href="https://twitter.com/JajaDavid8">@jajadavid8</a></li>
<li>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/david-jaja-8084251b4/">David Jaja</a></li>
<li>Email: Jajadavidjid@gmail.com</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create an Interactive Button Component in Figma ]]>
                </title>
                <description>
                    <![CDATA[ Designers are always searching for tools that help ease their workflow and create innovative solutions for their users. This ranges from components, style guides, and design systems, to plugins and extensions. In this article, we're going to look at ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-an-interactive-button-component-in-figma/</link>
                <guid isPermaLink="false">66d03a25daf2a38a6b1e1d0b</guid>
                
                    <category>
                        <![CDATA[ figma ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Faith Olohijere ]]>
                </dc:creator>
                <pubDate>Wed, 06 Mar 2024 18:44:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/pexels-jess-bailey-designs-810079.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Designers are always searching for tools that help ease their workflow and create innovative solutions for their users. This ranges from components, style guides, and design systems, to plugins and extensions.</p>
<p>In this article, we're going to look at components as features which can help boost your efficiency as a designer. I'll show you how to create an interactive button component using Figma.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-what-are-components">What are Components?</a><br>– <a class="post-section-overview" href="#heading-button-components">Button components</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-an-interactive-button-component-in-figma">How to Create an Interactive Button Component in Figma</a><br>– <a class="post-section-overview" href="#heading-build-the-button-component">Build the button component</a><br>– <a class="post-section-overview" href="#heading-how-to-create-variants">How to create variants</a><br>– <a class="post-section-overview" href="#heading-how-to-create-hover-and-active-states">How to create hover and active states</a><br>– <a class="post-section-overview" href="#heading-how-to-create-other-button-states">How to create other button states</a><br>– <a class="post-section-overview" href="#heading-how-to-group-buttons-by-states">How to group buttons by states</a><br>– <a class="post-section-overview" href="#heading-how-to-make-the-button-components-interactive">How to make the button components interactive</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-prerequisites">Prerequisites:</h2>
<p>To get the most out of this article, it'll be helpful to have basic knowledge of how to use Figma and its features. But note that this is not necessary, as I wrote this article for everyone – irrespective of their individual level of knowledge.</p>
<p>This article is for everyone who is interested in learning more about components, reusable elements, Figma, and design in general.</p>
<h2 id="heading-what-are-components">What are Components?</h2>
<p>Components are reusable design elements that you can use multiple times within a project or across different projects. </p>
<blockquote>
<p>Components are interactive building blocks for creating a user interface. They can be organized into categories based on their purpose: Action, containment, communication, navigation, selection, and text input. – Material Design 3</p>
</blockquote>
<p>Components can range from simple elements like buttons or icons to more complex structures like navigation bars or entire UI modules. They help maintain consistency and uniformity in a design, they are scalable, and they're very helpful for collaboration.</p>
<h3 id="heading-button-components">Button Components</h3>
<p>Buttons, sometimes called CTAs, are elements which allow a user to carry out a specific action like signing up, buying a product, subscribing to a newsletter, and so on. They come in different formats and sizes, and are very important elements in design.</p>
<p>Button components typically consist of visual attributes such as shape, size, color, and typography to convey their functionality and encourage user interaction. They can vary in style and appearance based on the design system, brand guidelines, or the context of their usage within an application or website. </p>
<h2 id="heading-how-to-create-an-interactive-button-component-in-figma">How to Create an Interactive Button Component in Figma</h2>
<p>Next, we're going to create an interactive button component in Figma. This button component will contain text only buttons, buttons with icons on either the left or right side of the text, and buttons with icons only. </p>
<p>The button component will contain different button states (default, hover, and active), and will be interactive.</p>
<p>This is very helpful for when you're designing interfaces with different use cases. For instance, you could want a button in your design to carry text and an accompanying icon, for a particular screen. In another screen, you might want to use an icon only button. If you have already created these different components, you'll save a lot of time.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/image-30.png" alt="Image" width="600" height="400" loading="lazy">
_Different button types (Icon only, Icon &amp; text, text only). Image from <a target="_blank" href="https://www.google.com/url?sa=i&amp;url=https%3A%2F%2Fwww.telerik.com%2Fdesign-system%2Fdocs%2Fcomponents%2Fbutton%2F&amp;psig=AOvVaw2RdR4WQVKTp_y542hJlwaB&amp;ust=1709772173745000&amp;source=images&amp;cd=vfe&amp;opi=89978449&amp;ved=0CBYQ3YkBahcKEwjQnoXps96EAxUAAAAAHQAAAAAQBA">Telerik</a>_</p>
<p>Let's get started!</p>
<h3 id="heading-build-the-button-component">Build the Button Component</h3>
<p>Open a new Figma file. If you don't have a Figma account, go ahead and create one at <a target="_blank" href="https://www.freecodecamp.org/news/p/3c725afb-cd49-490c-b122-0115d9b1780a/figma.com">figma.com</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Button-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Opening a new Figma file</em></p>
<p>Next, click on the Text icon on the left hand panel, and type <em>Button</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Button-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Typing "button" in the search bar.</em></p>
<p>Next, add auto-layout (Shift + A). </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Button-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding auto-layout</em></p>
<p>Make the horizontal button padding to be 36px and the vertical padding 12px. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Button-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding horizontal and vertical padding</em></p>
<p>Also, give the button a border radius of 8px.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Button-5.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding a border radius.</em></p>
<p>Add a fill to the button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Button-6.png" alt="Image" width="600" height="400" loading="lazy">
<em>Moving to the "fill" section.</em></p>
<p>I'll choose the color code #1C199, which is a shade of blue.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Button-7.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing a color code.</em></p>
<p>Next, I'll make the text a little bit bolder. To do that, click on the text, and move to the font section on your right panel.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-8.png" alt="Image" width="600" height="400" loading="lazy">
<em>Moving to the font section.</em></p>
<p>I'll give the button a font size of 16px, and make the weight "medium".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-10.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changing the font size to 16 px</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-11.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changing the font weight to medium.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-9.png" alt="Image" width="600" height="400" loading="lazy">
<em>Showing the edited text</em></p>
<p>Next, I'll add any icon of my choice to the button frame. This will enable me easily create a button component with icons, and not just text when the time comes.</p>
<p>To add an icon, I'll use a Figma plugin called <em>Iconify</em>, which is one of the largest icon collections in Figma. To do this, right-click on your canva and a menu will pop-up. Go to the <em>Plugins</em> tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-12.png" alt="Image" width="600" height="400" loading="lazy">
<em>Opening Plugins</em></p>
<p>A list of the recent plugins you have used will pop-up. You'll also see all the <em>Saved</em> plugins you have. The first plugin on my list is Iconify (that's because I use it a lot, lol). Now, I'll just click on Iconify and search for the particular icon I want to use.</p>
<p>If you have never used a plugin before, and so there are no plugins on your list, you can use the resources section to search for your plugin of choice and save it to your list.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-65.png" alt="Image" width="600" height="400" loading="lazy">
<em>Going to the resources section</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-64.png" alt="Image" width="600" height="400" loading="lazy">
<em>Searching for plugins</em></p>
<p>I want to use the <em>forward arrow</em> icon, so I'll just search for that using the search field on the plugin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-13.png" alt="Image" width="600" height="400" loading="lazy">
<em>Searching for the forward arrow icon.</em></p>
<p>A lot of forward arrow icons from different collections will pop-up so, I'll just choose any particular one that works best for me, in this case, a forward arrow icon from <em>IonIcons</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-14.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting a particular forward arrow icon</em></p>
<p>I'll select the icon and click on the <em>Import icon</em> button so it can appear on my Figma file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-15.png" alt="Image" width="600" height="400" loading="lazy">
<em>Importing the icon to your file</em></p>
<p>Next, we'll reduce the size of the icon to whatever height and width we want it to be. It's currently on 48 x 48 and I want it to be 24 x 24.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-16.png" alt="Image" width="600" height="400" loading="lazy">
<em>Icon size currently 48x48</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-17.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changing icon size to 24x24</em></p>
<p>We'll also change the colour of the icon to match the text colour (white). To do this, make sure the icon is selected and then scroll down to <em>Selection colours</em> to input the color code, which in this case is #FFFFFF.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-18.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changing icon colour to white (#FFFFFF)</em></p>
<p>Next, we'll add the icon inside the button frame. To do this, just drag your icon inside the frame.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-19.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dragging arrow icon into the button frame</em></p>
<p>You'll notice that the frame size increases to accommodate the icon added. </p>
<p>Next, duplicate the icon and move it to the other side of the text. Duplicating the icon will help us easily create button components with icons on either sides of the text later.</p>
<p>To do this, simply use Ctrl + D, and move the duplicated icon to the other side.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-20.png" alt="Image" width="600" height="400" loading="lazy">
<em>Using Ctrl + D to duplicate an icon</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-21.png" alt="Image" width="600" height="400" loading="lazy">
<em>Moving the duplicated icon to the other side of the frame.</em></p>
<p>Next, I'll hide both icons because I want to create my first button component (text only button). I'll rename the frame to Button.</p>
<p>To hide both icons, move to the layers panel on your left, and click on the eye icon by the side of the assets you want to hide.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-22.png" alt="Image" width="600" height="400" loading="lazy">
<em>Moving to the layers panel to hide the icons</em></p>
<p>You'll notice that the frame resizes automatically once both icons are hidden.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-23.png" alt="Image" width="600" height="400" loading="lazy">
<em>Button frame with hidden icons</em></p>
<p>I'll then rename the frame to <em>Button</em>. To do that, double click on the heading of the frame, and rename.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-24.png" alt="Image" width="600" height="400" loading="lazy">
<em>Double-clicking the frame</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-25.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed button frame</em></p>
<h3 id="heading-how-to-create-variants">How to Create Variants</h3>
<p>Next, we'll make the button frame a variant. </p>
<p>Variants help you create multiple versions or states of a component. They're very useful when designing interfaces that have different states or variations, such as buttons with different sizes or designs, like we're creating here.</p>
<p>To make the button frame a variant, double-click on the component icon at the top of your screen.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-26.png" alt="Image" width="600" height="400" loading="lazy">
<em>Moving to the component icon at the top of the screen and double-clicking</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-27.png" alt="Image" width="600" height="400" loading="lazy">
<em>Variant of the button component</em></p>
<p>Next, I'll add another variant because I want to have three states for the button (Default, Hover, and Active). To add another variant, click on the plus icon on any of the already existing variants.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-28.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the olus icon on a variant to add nother variant</em></p>
<p>Automatically, a new variant will be added.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-29.png" alt="Image" width="600" height="400" loading="lazy">
<em>Added third variant</em></p>
<p>Next, I'll increase the size of the component frame so it can accommodate other variants that will be added. To do this, simply select the whole component, and drag to your satisfied size.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-30.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting the component frame</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-31.png" alt="Image" width="600" height="400" loading="lazy">
<em>Increasing the width of the component frame.</em></p>
<h3 id="heading-how-to-create-hover-and-active-states">How to Create Hover and Active States</h3>
<p>Next, I'll tweak the last two buttons (hover and active states), so the difference between the three button states will be obvious. To do this, I'll make the hover state lighter, and the active state darker.</p>
<p>For the hover state, I'll change the color code to #392AE7, which is a lighter shade of blue. Make sure the particular button is selected so the changes take effect:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-32.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changing color code for the hover state</em></p>
<p>For the active state, I'll change the color code to #19107A which is a slightly darker shade of blue.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-33.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changing the color code of the active state</em></p>
<h3 id="heading-how-to-create-other-button-states">How to Create Other Button States</h3>
<p>Next, we want to create other button states (buttons with icons on either side of the text, and with icons only).</p>
<p>To start with, I'll duplicate the three buttons. To do this, select the three buttons and duplicate using Ctrl + D.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-34.png" alt="Image" width="600" height="400" loading="lazy">
<em>Duplicating the three buttons</em></p>
<p>Next, we want to create button components with text and a left icon. To do this, click on the eye on the left icons on each of the icons to reveal them.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-35.png" alt="Image" width="600" height="400" loading="lazy">
<em>Revealing the icons on the left side of the buttons</em></p>
<p>Next, we want to create button components with text and a right icon.</p>
<p>To do this, duplicate the buttons again, and do the same for the right icons.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-36.png" alt="Image" width="600" height="400" loading="lazy">
<em>Duplicating the buttons a second time</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-37.png" alt="Image" width="600" height="400" loading="lazy">
<em>Revealing the icons on the right side</em></p>
<p>Lastly, we want to create button components with icons only.</p>
<p>To do that, we'll duplicate the buttons one last time to hide the text.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-38.png" alt="Image" width="600" height="400" loading="lazy">
<em>Duplicating the buttons a third time</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-39.png" alt="Image" width="600" height="400" loading="lazy">
<em>Hiding the text</em></p>
<p>I'll make the <em>icon only</em> frames a square shape. To do that, select the three frames and drag to resize.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-40.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting the 'icons only' frames</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-41.png" alt="Image" width="600" height="400" loading="lazy">
<em>Resizing the frames</em></p>
<p>I'll now resize the component frame to fit its content.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-42.png" alt="Image" width="600" height="400" loading="lazy">
<em>Resizing the component frame.</em></p>
<p>Next, we'll rename the different button states so it'll be easy to identify them. First, select the whole component frame. Then move to the section labelled <em>Properties</em>, and change <em>Property 1</em> to <em>Button</em> to show that this is a button component.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-43.png" alt="Image" width="600" height="400" loading="lazy">
<em>Moving to properties section</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-44.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renaming the component frame</em></p>
<p>Next, we'll rename the button frames by icons. Select the first three frames horizontally, and go over to the <em>Current variant</em> section. Rename them <em>No icons</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-46.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting first three buttons and renaming them</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-47.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed no icons buttons</em></p>
<p>We'll do same for the next three buttons, and name them <em>Left Icons</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-48.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed left icons' buttons</em></p>
<p>We'll do the same thing for the next set, renaming them <em>Right Icons</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-49.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed right icons' buttons</em></p>
<p>Finally, for the last set, we'll rename the buttons <em>Icons only</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-50.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed icons only buttons</em></p>
<h3 id="heading-how-to-group-buttons-by-states">How to Group Buttons by States</h3>
<p>Next, we'll group the buttons by states and name them. We'll start with the first state: <em>Default</em>. Select all the button frames under default and move to the <em>Current variant section</em> on the right hand panel. Click on the configure icon to edit the component configuration.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-51.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on configure icon</em></p>
<p>Click on the description box to add a description. In this case, I'll simply type <em>Default state</em>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-55.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding a description</em></p>
<p>Do the same for the other two states – hover and active.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-53.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding a description for the hover state</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-54.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding a description for the active state</em></p>
<h3 id="heading-how-to-make-the-button-components-interactive">How to Make the Button Components Interactive</h3>
<p>To start, switch to the Prototype tab, located at the top of your screen, right-hand panel.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-56.png" alt="Image" width="600" height="400" loading="lazy">
<em>Switching to prototype mode</em></p>
<p>Next, add an interaction from the first to the second <em>no icon</em> button frame. To do this, click on the first button frame and drag the plus icon to the second frame.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-57.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding an interaction</em></p>
<p>This will bring up a list of interaction options and settings  for the animation. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-58.png" alt="Image" width="600" height="400" loading="lazy">
<em>Bringing up interaction setting</em></p>
<p>Change <em>On click</em> to <em>While hovering</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-60.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changing interaction type to "while hovering"</em></p>
<p>Do the same for the next button frame but, instead of <em>While hovering</em>, change to <em>While pressing</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-61.png" alt="Image" width="600" height="400" loading="lazy">
<em>Animating the third button frame</em></p>
<p>Now, repeat the same steps for the other sets.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Button-62.png" alt="Image" width="600" height="400" loading="lazy">
<em>Repeating the animation steps for the other button sets.</em></p>
<p>Voilà, you just created an interactive button component. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Components help enhance your designs and make them more efficient. They also help you save time and they improve consistency across your designs. But they can only help when they're created the right way.</p>
<p>Practicing often will help improve your ability to create helpful reusable components. Remember, make every decision with your users in mind.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Motion Sensitivity? How to Design Accessible Web Animations ]]>
                </title>
                <description>
                    <![CDATA[ As web developers, we love a good animation, right? But let's be honest, sometimes we get caught up in the wow factor and forget that our websites exist for real people with diverse needs.  One hidden hurdle for some users is motion sensitivity. It m... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/web-sensitivity-how-to-design-accessible-animations/</link>
                <guid isPermaLink="false">66bb8c556b3bd8d6bf25ae5d</guid>
                
                    <category>
                        <![CDATA[ Accessibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elizabeth Lola ]]>
                </dc:creator>
                <pubDate>Wed, 07 Feb 2024 21:51:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/pexels-pixabay-315938-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As web developers, we love a good animation, right? But let's be honest, sometimes we get caught up in the wow factor and forget that our websites exist for real people with diverse needs. </p>
<p>One hidden hurdle for some users is motion sensitivity. It might not be something we think about every day, but it can have a big impact on how people experience the internet.</p>
<p>In this article, I want to shine a light on <strong>motion sensitivity</strong>. We'll explore what it's like, the conditions it's linked to, and how it can affect someone's ability to enjoy using a website. </p>
<p>My goals for this article are: </p>
<ol>
<li>To get you thinking about creating web experiences that are comfortable and welcoming for everyone. </li>
<li>To equip you with practical tips to make that happen. Because an inclusive web is a better web for everyone.</li>
</ol>
<h2 id="heading-what-is-motion-sensitivity">What is Motion Sensitivity?</h2>
<p>Motion sensitivity isn't just a technical term – it refers to how we experience the digital world, especially for those whose sensitivities go beyond what meets the eye. So, let's unravel this concept and see why it matters.</p>
<p>According to <a target="_blank" href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7418000/#:~:text=Motion%20sensitivity%20is%20characterized%20by,dizziness%20%5B1%2D3%5D.">National Library of Medicine</a>, motion sensitivity refers to a condition where a person experiences symptoms such as dizziness, nausea, and imbalance in response to motion. This can be caused by a variety of factors, including inner ear problems, neurological disorders, and certain medications. </p>
<p>People with motion sensitivity may have difficulty tolerating activities that involve moving, such as riding in cars and even certain motion animations.</p>
<p>Maybe you've taken a long road trip and experienced motion sickness. Or you've visited the cinema to see a 3D movie and, instead of enjoying the experience, you end up with headaches, migraine, dizziness, or nausea. Then you understand how serious motion sensitivity can be.</p>
<h3 id="heading-how-motion-sensitivity-impacts-people">How Motion Sensitivity Impacts People</h3>
<p>For some people, motion effects like parallax scrolling can be annoying, but the effects of motion sensitivity go beyond a mere inconvenience. It can disrupt the digital experience and, more importantly, affect the well-being of those navigating the space. </p>
<p>Some people might feel dizzy, nauseous, or experience headaches or migraines when faced with certain animations or transitions. For them, accessing digital content becomes more than just a click – it's a consideration of their comfort and health.</p>
<h3 id="heading-insights-into-related-disorders">Insights into Related Disorders</h3>
<p>To truly understand motion sensitivity, I believe we need to explore the conditions linked to it, mainly vestibular disorders and visual motion sensitivity.</p>
<p><strong>Vestibular Disorders</strong> impact the inner ear and how the brain processes spatial information. For someone with vestibular disorders, simple tasks like maintaining balance or handling motion stimuli can become challenging.</p>
<p><strong>Visual Motion Sensitivity</strong> is about heightened sensitivity to visual stimuli, leading to discomfort or adverse reactions to certain types of motion. For someone with visual motion sensitivity, navigating websites with specific animations or scrolling behaviors can be a struggle.</p>
<p>By diving into these facets of motion sensitivity, we lay the groundwork for creating digital spaces that acknowledge and respect diverse user experiences. </p>
<h3 id="heading-so-why-does-this-matter">So, Why Does this Matter?</h3>
<p>Well, I think it is as simple as this: everyone deserves to enjoy the digital world without feeling unwell. Understanding motion sensitivity helps us create websites, games, and apps that are more inclusive and comfortable for everyone, not just folks with superhero vision.</p>
<p>Let's explore why designing with motion sensitivity in mind is not just a best practice but a step towards a more inclusive online world.</p>
<h3 id="heading-how-common-is-motion-sensitivity">How Common is Motion Sensitivity?</h3>
<p>Motion sensitivity is more common than you might think. According to <a target="_blank" href="https://archivesphysiotherapy.biomedcentral.com/articles/10.1186/s40945-020-00077-9#:~:text=It%20has%20been%20reported%20that,men%20%5B2%2C%203%5D.">this article</a> from Archives of Physiotherapy, it has been reported that 28.4% of the population experience motion sensitivity. Also, according to <a target="_blank" href="https://en.wikipedia.org/wiki/Motion_sickness#:~:text=of%20motion%20sickness.-,Epidemiology,medium%20to%20high%20motion%20sickness.">this article</a>:</p>
<blockquote>
<p>Nearly all people are affected with sufficient motion and most people will experience motion sickness at least once in their lifetime. Susceptibility, however, is variable, with about one-third of the population being highly susceptible while most other people are affected under extreme conditions. Women are more easily affected than men. </p>
</blockquote>
<p>These statistics underscore the need for web designers and developers to consider motion sensitivity in our creations. They highlight that what might be a visually engaging animation for one user could be an obstacle for another.</p>
<h2 id="heading-how-to-identify-motion-sensitive-triggers-in-animations">How to Identify Motion-Sensitive Triggers in Animations</h2>
<p>Animation can enhance engagement and help guide users through the app. But it is vital that we scrutinize the types of animations we incorporate into our designs, particularly when aiming for motion-friendly experiences. </p>
<p>Let's explore these potential triggers and discuss alternatives to ensure a more inclusive design.</p>
<h3 id="heading-rapid-or-flickering-animations">Rapid or Flickering Animations</h3>
<ul>
<li><strong>Trigger Potential:</strong> Quick, flickering animations can be disorienting for users with motion sensitivity, leading to discomfort or headaches. Examples of these types of animations include rapidly blinking notifications, flickering banners, or flashing call-to-action buttons.</li>
<li><strong>Alternative Approach:</strong> Opt for smoother transitions like subtle fades or slides, avoiding rapid flickering effects for a more comfortable experience.</li>
</ul>
<h3 id="heading-overly-complex-transitions">Overly Complex Transitions</h3>
<ul>
<li><strong>Trigger Potential</strong>: Elaborate loading animations with intricate patterns, complex slide-in effects, or overly detailed transitions between pages may overwhelm users, causing sensory overload for those with motion sensitivity.</li>
<li><strong>Alternative Approach</strong>: Simplify transitions, focus on clarity and purpose. Strive for elegance in design without unnecessary visual complexity.</li>
</ul>
<h3 id="heading-bouncing-or-elastic-motions">Bouncing or Elastic Motions</h3>
<ul>
<li><strong>Trigger Potential</strong>: Animations with bouncing or elastic movements can induce dizziness or nausea in motion-sensitive users. Examples include buttons that bounce upon interaction or elastic-scrolling effects.</li>
<li><strong>Alternative Approach</strong>: Choose more subtle easing functions for animations, providing a smoother and less physically demanding experience.</li>
</ul>
<h3 id="heading-high-speed-animations">High-Speed Animations</h3>
<ul>
<li><strong>Trigger Potential</strong>: High-speed carousels, rapid image sliders, or quick-scrolling features may challenge users with motion sensitivity, potentially leading to feelings of discomfort or disorientation.</li>
<li><strong>Alternative Approach</strong>: Allow users to control animation speeds or default to slower, more deliberate transitions for a universally comfortable pace.</li>
</ul>
<h3 id="heading-continuous-auto-scrolling">Continuous Auto-Scrolling</h3>
<ul>
<li><strong>Trigger Potential</strong>: Auto-scrolling features that move content continuously without user interaction, like automatic slideshows or news tickers, can be unsettling for users with motion sensitivity.</li>
<li><strong>Alternative Approach</strong>: Implement user-initiated scrolling, providing control to the user and avoiding unexpected motion.</li>
</ul>
<h3 id="heading-flashing-or-intense-color-changes">Flashing or Intense Color Changes</h3>
<ul>
<li><strong>Trigger Potential</strong>: Flashing animations or sudden, intense color changes can be visually overwhelming and trigger discomfort. Examples include flashing banners, intense color changes on hover, or rapidly changing background colors.</li>
<li><strong>Alternative Approach</strong>: Maintain a consistent color palette and avoid rapid, drastic color shifts. Consider softer transitions for color changes.</li>
</ul>
<h3 id="heading-rotational-movements">Rotational Movements</h3>
<ul>
<li><strong>Trigger Potential</strong>: Rotational animations, such as spinning logos or rotating carousels, may cause dizziness or vertigo for individuals with vestibular disorders or motion sensitivity.</li>
<li><strong>Alternative Approach</strong><em>:</em> Minimize or eliminate rotational motions, especially in situations where they may not be essential for understanding the content.</li>
</ul>
<p>By recognizing these potential triggers and adopting alternative approaches, we can create digital experiences that are more considerate and welcoming for users with motion sensitivity. </p>
<p>The goal is not to stop adding animations but to design with empathy, ensuring that motion enhances rather than detracts from the user experience.</p>
<h2 id="heading-how-to-use-reduce-motion-preferences">How to Use Reduce-Motion Preferences</h2>
<p>One significant stride towards motion-friendly web design is utilizing the <code>reduce-motion</code> preferences embedded in operating systems and browsers. This preference provide users with the option to minimize or eliminate unnecessary animations. </p>
<p>By recognizing and respecting these user preferences, we can significantly enhance the accessibility of web applications.</p>
<h3 id="heading-incorporate-reduced-motion-features">Incorporate Reduced Motion Features</h3>
<p>For developers, integrating reduced motion features into web applications involves a combination of coding practices and user interface considerations. </p>
<p>Begin by identifying areas where animations can be toned down or replaced with static alternatives. Implementing conditional checks for reduce-motion preferences in your codebase allows your web application to adapt dynamically, providing a smoother experience for users who opt for reduced motion.</p>
<h4 id="heading-css-prefers-reduced-motion-media-feature">CSS prefers-reduced-motion Media Feature</h4>
<pre><code class="lang-css"><span class="hljs-selector-class">.animated-element</span> {
  <span class="hljs-attribute">animation</span>: pulse <span class="hljs-number">1s</span> linear infinite both;
}

<span class="hljs-comment">/* Tone down the animation */</span>
<span class="hljs-keyword">@media</span> (prefers-reduced-motion) {
  <span class="hljs-selector-class">.animated-element</span> {
    <span class="hljs-attribute">animation</span>: smooth <span class="hljs-number">4s</span> linear infinite both;
  }
}
</code></pre>
<h4 id="heading-javascript-reduced-motion-detection">JavaScript Reduced Motion Detection</h4>
<pre><code class="lang-js"><span class="hljs-comment">// Check if the user prefers reduced motion using JavaScript</span>

<span class="hljs-keyword">const</span> prefersReducedMotion = <span class="hljs-built_in">window</span>.matchMedia(<span class="hljs-string">'(prefers-reduced-motion: reduce)'</span>).matches;

<span class="hljs-comment">// Example of adjusting animation based on reduced motion preference</span>

<span class="hljs-keyword">const</span> animatedElement = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.animated-element'</span>);
<span class="hljs-keyword">if</span> (prefersReducedMotion) {
  animatedElement.style.animation = <span class="hljs-string">'smooth 4s linear infinite both'</span>;
} <span class="hljs-keyword">else</span> {
  animatedElement.style.animation = <span class="hljs-string">'pulse 1s linear infinite both'</span>;
}
</code></pre>
<h3 id="heading-test-your-animation-on-chrome">Test Your Animation on Chrome</h3>
<p>While basic accessibility checks are readily available, Chrome DevTools offers advanced capabilities through its hidden <strong>Rendering</strong> tool. </p>
<p>One of the options available in the rendering tool is the option to test your animation for when a user enables <code>prefers-reduced-motion</code>. Here's how to leverage it:</p>
<ul>
<li>Click the customize (three dots) icon in the DevTools panel</li>
<li>Select more tools</li>
<li>Select <strong>Rendering</strong> option from the list of options</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-07-at-10.44.34.png" alt="The chrome dev tool" width="600" height="400" loading="lazy">
<em>Select Rendering under more tools</em></p>
<ul>
<li>Once enabled, the <strong>Rendering</strong> tab appears in DevTools.</li>
<li>Look for the option named "<strong>Emulate CSS media feature prefers-reduced-motion</strong>."</li>
<li>Enable this option to preview how your website's animations appear for users who have set their device or browser to reduce motion.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-07-at-10.51.13.png" alt="Chrome rendering tool for reduced-motion" width="600" height="400" loading="lazy"></p>
<p>When a user has <code>prefers-reduced-motion</code> enabled, avoid completely removing animations. Aim to provide users with a smoother experience rather than completely excluding them from the interactive experience.</p>
<h2 id="heading-motion-sensitivity-tips-and-best-practices">Motion Sensitivity Tips and Best Practices</h2>
<p>Let's explore tips and best practices to incorporate into our designs:</p>
<ol>
<li><strong>Subtle Animations:</strong> Opt for subtle animations that convey information without being overwhelming. Gentle fades, transitions, and loading effects can enhance the user experience without causing discomfort.</li>
<li><strong>Adjustable Speeds:</strong> Provide users with the ability to control animation speeds. Implement settings within your application that allow users to customize the speed of transitions, ensuring a comfortable experience for everyone.</li>
<li><strong>Clear Navigation Signals:</strong> Use motion to guide users intuitively. For instance, employ subtle animations to indicate a change in state or to draw attention to important elements, ensuring that users with motion sensitivity can follow the flow without feeling disoriented.</li>
<li><strong>User Testing:</strong> Conduct thorough user testing, specifically with individuals who experience motion sensitivity. Gather feedback to refine your design, ensuring that it meets the needs of the diverse user base.</li>
<li><strong>Document and Communicate:</strong> Clearly document your approach to motion-friendly design in your project documentation. This not only serves as a reference for your team but also communicates your commitment to accessibility to stakeholders and users.</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Motion sensitivity isn't a rare exception – it's a shared experience for many people. Our responsibility as web developers is not merely to acknowledge this reality but to actively integrate inclusivity into the DNA of our creations.</p>
<p>By identifying potential triggers and implementing reduced motion features using technologies like <code>prefers-reduced-motion</code> in CSS and JavaScript, we create spaces that accommodate diverse needs without compromising on engagement. </p>
<p>Accessibility is not a trend, it's a fundamental ethos that shapes the future of the internet into one where everyone regardless of their abilities can use the internet with comfort.</p>
<p>Thank you so much for reading this article, if you found it helpful consider sharing. Happy coding!</p>
<p>You can connect with me on <a target="_blank" href="https://www.linkedin.com/in/elizabeth-meshioye/">LinkedIn</a> or <a target="_blank" href="https://github.com/Lezette">GitHub</a>.</p>
<h3 id="heading-references">References</h3>
<ul>
<li>Val Head. Designing Safer Web Animation For Motion Sensitivity (September 08, 2015) https://alistapart.com/article/designing-safer-web-animation-for-motion-sensitivity/</li>
<li>Chaudhary, S., Saywell, N., Kumar, A., &amp; Taylor, D. (2020). Visual Fixations and Motion Sensitivity: Protocol for an Exploratory Study. JMIR Research Protocols, 9(7). https://doi.org/10.2196/16805</li>
<li>Albalwi, A.A., Johnson, E.G., Alharbi, A.A. et al. Effects of head motion on postural stability in healthy young adults with chronic motion sensitivity. Arch Physiother10, 6 (2020). https://doi.org/10.1186/s40945-020-00077-9</li>
<li>Motion sickness. (2024, January 1). In Wikipedia. https://en.wikipedia.org/wiki/Motion_sickness</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use New CSS Features to Build a Progress Indicator ]]>
                </title>
                <description>
                    <![CDATA[ For the last 7 months, I’ve had my head down building Component Odyssey. It’s been a richly fulfilling project and I’m eager for people to take the course and learn heaps about building component libraries using web components. I’ve seen some incredi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-new-css-features-to-build-a-progress-indicator/</link>
                <guid isPermaLink="false">66bb8e04b0d3ac3d7acde3ee</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Andrico Karoulla ]]>
                </dc:creator>
                <pubDate>Tue, 09 Jan 2024 15:39:50 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/open-graph.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>For the last 7 months, I’ve had my head down building <a target="_blank" href="https://component-odyssey.com/">Component Odyssey</a>. It’s been a richly fulfilling project and I’m eager for people to take the course and learn heaps about building component libraries using web components.</p>
<p>I’ve seen some incredible demos over the past year, and wanted to sink my teeth into some of these cool new features. So I used some downtime over the Christmas period to cram tons of new CSS features into a lesson progress indicator for the Component Odyssey platform. </p>
<p>The result is the following progress indicator that shows how much of the page the user has scrolled:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/component-odyssey-indicator.gif" alt="the fully completed progress indicator as it exists on Component Odyssey" width="600" height="400" loading="lazy"></p>
<p>Building it gave me some exposure to some of the latest CSS features like:</p>
<ul>
<li><code>animation-timeline: scroll()</code></li>
<li>CSS trig functions, <code>sin()</code> and <code>cos()</code></li>
<li><code>color-mix()</code></li>
<li>the <code>@property</code> at-rule</li>
</ul>
<p>I know the risks of building something with a particular tool in mind. As the saying goes “When all you have is a hammer, then <em>something something</em> nails”.</p>
<p>Yes, I have a hammer, and I’m going to smash the walls down with it.</p>
<p>In this article, I’ll run through how to create a pared-down version of this swanky progress animation while still using all of the CSS features mentioned above. I’ll also show you how to gracefully handle browsers that don’t support these features through <strong>progressive enhancement</strong>.</p>
<p>If you want to follow along, then it’s best to use the latest versions of Chrome or Safari – currently Firefox doesn’t have general support for properties like <code>animation-timeline</code>. Get started by jumping into the <a target="_blank" href="https://codepen.io/andrico1234/pen/WNmQrGK">starter Codepen</a>.</p>
<p>If you want to peruse the finished code, you can <a target="_blank" href="https://codepen.io/andrico1234/pen/qBvdjLd">check it out here.</a></p>
<h2 id="heading-how-to-create-the-markup">How to Create the Markup</h2>
<p>I’ve already provided a little markup to simulate a page with enough content that you'll need to scroll to get to the bottom. To get started creating the progress indicator, you’ll need to add some more markup.</p>
<p>The markup itself is really simple – we’ll only need to create 3 div elements.</p>
<p>The outer element is responsible for the positioning and layout of the loader. We’ll give this a class of <code>wrapper</code>.</p>
<p>The middle element is responsible for rendering the track to the screen. We’ll give this element a class of <code>progress</code>. We’ll later use an <code>::after</code> pseudo-element to create the <em>indicator thumb</em>.</p>
<p>The innermost element will be used to create the circular hole in the middle, making the indicator look like a low-calorie doughnut. This will have a class of <code>inner</code>.</p>
<p>Take a look at the following if you need a hand visualising the structure:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/markup-structure.png" alt="A visual representation of the information outlined above" width="600" height="400" loading="lazy">
<em>Illustration of the markup structure</em></p>
<p>Provide the following markup as the first child of the <code>main</code> element creates the following 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">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"progress"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"inner"</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>
<h3 id="heading-applying-the-base-css-to-the-markup">Applying the Base CSS to the Markup</h3>
<p>You’ll also need to apply the following styles to give the markup a base visual appearance:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.wrapper</span> {
    <span class="hljs-attribute">--size</span>: <span class="hljs-number">80px</span>;

    <span class="hljs-attribute">position</span>: fixed;
    <span class="hljs-attribute">width</span>: <span class="hljs-built_in">var</span>(--size);
    <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>/<span class="hljs-number">1</span>;
    <span class="hljs-attribute">top</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">left</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">justify-content</span>: center;
}

<span class="hljs-selector-class">.progress</span> {
    <span class="hljs-attribute">--track-size</span>: <span class="hljs-number">16px</span>;

    <span class="hljs-attribute">width</span>: <span class="hljs-built_in">var</span>(--size);
    <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>/<span class="hljs-number">1</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
}

<span class="hljs-selector-class">.inner</span> {
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">width</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - var(--track-size));
    <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>/<span class="hljs-number">1</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--background-color);
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
    <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">right</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">bottom</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin</span>: auto;
}
</code></pre>
<p>Most of the CSS here shouldn’t come as a shock to you, so I won’t go over it line by line. But I will touch on some of the more interesting bits.</p>
<p>In <code>.wrapper</code>, we’re fixing the element to the top left of the screen, and we're using Flexbox to center the children horizontally and vertically.</p>
<p>💡 I learned that if you want an element to share the same value for both its width and height, you just set the width and use <code>aspect-ratio: 1/1</code>. The browser will implicitly set the height. </p>
<p>This is a neat trick because you won’t have to define the same value twice, and it makes it easier to guarantee that the width and the height share the same value.</p>
<p>As for the <code>.inner</code> element, I’ve used a mix of absolute positioning and the <code>margin: auto</code> to center it in the middle of the <code>.progress</code> element. We’ve also deducted the <code>--track-size</code> from the full width of the container, to ensure that it’s correctly positioned over the <code>.progress</code> element.</p>
<p>You won’t be able to see anything just yet, but if you add a temporary <code>background-color: red</code> to the <code>.progress</code> element, it should render as follows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/basic-ui.png" alt="a basic doughnut shaped indacator without any animation" width="600" height="400" loading="lazy">
<em>Image showing the current state of the progress indicator - a red circle</em></p>
<h2 id="heading-how-to-create-an-animated-progress-indicator">How to Create an Animated Progress Indicator</h2>
<p>Creating a scroll-driven animation of this kind requires a lot of new CSS features that you may have not used before. Instead of learning everything all at once, we’ll start by decoupling the animation from the scrolling mechanics.</p>
<p>That way, by the end of this section, you should have the following animation that plays automatically:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/infinite-loading.gif" alt="A progress indicator playing automatically in an infinite loop" width="600" height="400" loading="lazy">
<em>Animation showing the initial stage of the progress indicator</em></p>
<p>We’ll start by creating a new animation called <code>load</code>:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@keyframes</span> load {
    0% {
        <span class="hljs-attribute">--progress</span>: <span class="hljs-number">0%</span>;
    }

    100% {
        <span class="hljs-attribute">--progress</span>: <span class="hljs-number">100%</span>;
    }
}
</code></pre>
<p>All this does is move the progress along from 0 to 100 over the course of the animation. </p>
<h3 id="heading-using-conic-gradient-to-indicate-the-current-progress">Using <code>conic-gradient</code> to Indicate the Current Progress</h3>
<p>In your <code>.progress</code> rule, add the following CSS properties:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.progress</span> {
    # Existing rules

    <span class="hljs-attribute">animation</span>: load linear <span class="hljs-number">1s</span> infinite;
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">conic-gradient</span>(
        from <span class="hljs-number">0deg</span> at <span class="hljs-number">50%</span> <span class="hljs-number">50%</span>,
        var(--red) <span class="hljs-built_in">var</span>(--progress),
        <span class="hljs-built_in">var</span>(--black) <span class="hljs-built_in">var</span>(--progress)
    )
}
</code></pre>
<p>The <code>animation</code> property should be pretty straightforward, but there’s a lot going on with the <code>background</code> rule, so let’s step through it.</p>
<p>For starters, we’re using a <code>conic-gradient</code> as it makes it easy for us to animate the background over 360 degrees, in the way shown in the animation above. We’re starting from the <code>0deg</code> position, which is top and center. We’re describing where we want the center of the gradient to be using <code>at 50% 50%</code>.</p>
<p><code>conic-gradient(from 0deg at 50% 50%)</code> alone would render something like the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/radial-gradient.png" alt="A visualisation of a radial gradient starting from the center, like a sonar radar" width="600" height="400" loading="lazy">
<em>Image showing a red circle witha slight gradient, the result of <code>conic-gradient(from 0deg at 50% 50%)</code> alone</em></p>
<p>Hopefully I’ve made it clear why that’s the case.</p>
<p>As for the the second and third arguments of the <code>conic-gradient</code> function, we’re linking the <code>--progress</code> variable (which is being calculated via the <code>load</code> animation) to the two colors. The <code>--red</code> is used to denote the completed progress, while the <code>--black</code> is used to denote the remaining position. </p>
<p>It might be confusing why they share the same <code>--progress</code> value. The <code>--progress</code> value for the <code>--red</code> value denotes where the gradient stop ends, while the <code>--progress</code> value for the <code>--black</code> denotes where the gradient stop begins. </p>
<p>Because it’s the last stop on the gradient, it’s implied that it ends at 100%. By setting the same <code>--progress</code> value to both stops in the gradient, we create a hard transition between the two colors. Without doing so, our progress indicator (with a <code>--progress</code> value set to 16%) would look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/radial-gradient-no-stop.png" alt="The progress indicator where the color gradient goes slowly from red to black" width="600" height="400" loading="lazy">
<em>Progress indicator with a red to black gradient and no animation</em></p>
<h3 id="heading-animating-the-gradient">Animating the Gradient</h3>
<p>Now, something strange is probably happening. Instead of your progress indicator transitioning gracefully across the entire perimeter of the circle, it’s instead flashing between the black and red.</p>
<p>Why is this happening?</p>
<p>This is because we’re making the browser interpolate between percentage values, which is something it can’t do automatically. Even though we’ve given the <code>--progress</code> variable a percentage value, the browser doesn’t assume that it’s always going to be a percentage value.</p>
<p>We can solve this by telling the browser that <code>--progress</code> will always be a percentage value. We can do this by explicitly defining the <code>--progress</code> property using the <code>@property</code> CSS rule. Just add the following to the top-level of your CSS:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@property</span> --progress {
    <span class="hljs-selector-tag">syntax</span>: '&lt;<span class="hljs-selector-tag">percentage</span>&gt;';
    <span class="hljs-selector-tag">inherits</span>: <span class="hljs-selector-tag">false</span>;
    <span class="hljs-selector-tag">initial-value</span>: 0%;
}
</code></pre>
<p>We’re telling the browser that <code>--progress</code> should only support percentage values and that the initial value is 0%. We’re also not interested in having the custom element inherit its value.</p>
<p>Finally, I don’t quite like the use of the <code>--black</code> variable to signify empty progress. It looks too stark. I’d like to create a lighter shade created from the black to ensure a more homogenous visual palette. This is something we can easily achieve using the <code>color-mix()</code> CSS function.</p>
<p>Jump back up to the <code>:root</code> CSS rule and add the following variable:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
    # your other CSS variables

    <span class="hljs-attribute">--grey</span>: <span class="hljs-built_in">color-mix</span>(in srgb, var(--black), transparent <span class="hljs-number">60%</span>);
}
</code></pre>
<p>The <code>color-mix</code> function lets us mix two colors together. In this case, we’re mixing the color stored in our black variable with some transparency, which will result in a partially see-through grey color. You’ll need to replace the reference to the <code>--black</code> variable in the <code>conic-gradient</code> function with <code>--grey</code> to see the color change in effect.</p>
<p>Now that we’ve defined our custom property, the browser will be able to interpolate the correct values during the entire animation, so it should now transition smoothly from start to finish.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/infinite-loading-1.gif" alt="A progress indicator playing automatically in an infinite loop" width="600" height="400" loading="lazy">
<em>Showing the animation functioning properly</em></p>
<h2 id="heading-how-to-enable-scroll-driven-animations">How to Enable Scroll-driven Animations</h2>
<p>The next stage of our animation journey is to tie our animation to the scrolling of the page.</p>
<p>This should only take us a couple of lines of CSS.</p>
<p>You’ll need to do two things: first adjust the <code>animation</code> property in your <code>.progress</code> class to remove the <code>infinite</code> value, and to change the duration from <code>1s</code> to <code>1ms</code>. We can’t remove the value altogether because Firefox needs it for scroll animations to work.</p>
<p>Next update your <code>.progress</code> class to include the following:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.progress</span> {
  # other CSS properties

    <span class="hljs-attribute">animation-timeline</span>: <span class="hljs-built_in">scroll</span>(nearest block);
}
</code></pre>
<p>The <code>animation-timeline</code> property tells the browser to tie the progress of the animation with a specific timeline. In this case it’s the scroll timeline, which we specify using the <code>scroll</code> function.</p>
<p>You can see I’m providing two arguments to <code>scroll()</code>: <code>nearest</code> and <code>block</code>.</p>
<p>The <code>nearest</code> value is used to tie the animation to the nearest ancestor that has a scrollbar. In this case it’s the document. If you’re certain that you only ever want to tie the animation to the document’s scrollbar, then you can swap out <code>nearest</code> for <code>root</code> instead.</p>
<p>The <code>block</code> property denotes the axis that we want to tie our animation to. For most cases this will be the vertical scrollbar, but for vertical writing modes, this will be the horizontal scrollbar.</p>
<p>Now that you’ve hooked up the animation to your page’s scroll, you should be able to scroll up and down the page and watch how your animation changes accordingly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/progress-complete.gif" alt="The basic progress indicator whose animation is tied to the progress of the page scroll" width="600" height="400" loading="lazy">
<em>Demo showing a user scorlling and the animation of the scroll element changing</em></p>
<h2 id="heading-how-to-progressively-enhance-your-scroll-animation">How to Progressively Enhance Your Scroll Animation</h2>
<p>While it’s exciting to use these new features in the browser, the <code>animation-timeline</code> property doesn’t have universal support across browsers yet. It’s still very new in Chrome, and it’s only available in Firefox behind a feature flag. If you try opening the code in Firefox, you’ll notice that the progress ring just appears with a finished animation.</p>
<p>In cases like this, it’s important to set up a solid base experience for all browsers, and then <em>progressively enhance</em> your webpage with the newer features on compatible browsers. Because the progress indicator isn’t critical for the application to function, we can just hide it away if the browser doesn’t support the <code>animation-timeline</code> property.</p>
<p>We can do this by moving our <code>.wrapper</code>, <code>.progress</code>, and <code>.inner</code> classes within CSS’s <code>@supports</code> at-rule, like so:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">animation-timeline:</span> scroll()) {
    <span class="hljs-selector-class">.wrapper</span> {}

    <span class="hljs-selector-class">.progress</span> {}

    <span class="hljs-selector-class">.inner</span> {}
}
</code></pre>
<p>Doing so ensures that if the browser doesn’t support <code>scroll()</code>, then it will ignore all of the styles contained within the rule.</p>
<h2 id="heading-how-to-add-the-indicator-thumb">How to Add the Indicator Thumb</h2>
<p>The final thing for us to add is a cool little indicator thumb, to both give our progress indicator a little more visual interest and to also let us play with the swanky CSS trigonometric functions.</p>
<p>The <em>indicator thumb</em> is the little circular element that indicates the exact current progress </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/thumb-indicator.png" alt="The indicator thumb placed at 4 o'clock on the progress indicator" width="600" height="400" loading="lazy">
<em>Illustration showing the indicator thumb (a dark dot on the progress indicator)</em></p>
<h3 id="heading-creating-the-thumbs-visual-appearance">Creating the Thumb's Visual Appearance</h3>
<p>To create the indicator thumb, start by writing the following CSS inside of the <code>@supports</code> block:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.progress</span><span class="hljs-selector-pseudo">::after</span> {
    <span class="hljs-attribute">--radius</span>: <span class="hljs-built_in">calc</span>(var(--size) / <span class="hljs-number">2</span>);
    <span class="hljs-attribute">--track-offset</span>: <span class="hljs-built_in">calc</span>(var(--track-size) / <span class="hljs-number">4</span>);

    <span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>;
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">aspect-ratio</span>: <span class="hljs-number">1</span>/<span class="hljs-number">1</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-built_in">calc</span>(var(--track-size) / <span class="hljs-number">2</span>);
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--red-dark);
    <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> - var(--track-offset));
    <span class="hljs-attribute">top</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">50%</span> - var(--track-offset));
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">1.5</span>);
}
</code></pre>
<p>This creates a new pseudo-element off of the <code>.progress</code> class, and gives it its visual appearance. Once added, the indicator thumb should live in the center progress element. We’re using the <code>--track-offset</code> variable to position the thumb correctly by taking into consideration the dimensions of the track.</p>
<p>⚠️ I’m also increasing the size of the thumb to using <code>scale()</code> so that its size in the DOM is still relative to the <code>--size</code> variable. This just means a little less math for us to worry about when setting the value for <code>--track-offset</code>. Using <code>scale()</code> makes it easy to change the size of the element without causing a shift in the DOM.</p>
<p>The next step is to use the <code>color-mix()</code> function again to create a dark red from the base red color. Add the following to your <code>:root</code> rule.</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
    # your other CSS variables

    <span class="hljs-attribute">--red-dark</span>: <span class="hljs-built_in">color-mix</span>(in srgb, var(--red), <span class="hljs-built_in">var</span>(--black) <span class="hljs-number">60%</span>);
}
</code></pre>
<p>Your progress indicator should look less like a UI widget and more like a dartboard:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/bullseye.png" alt="the thumb is in the center of the progress indicator" width="600" height="400" loading="lazy">
<em>Animation/indicator thumb in progress</em></p>
<h3 id="heading-positioning-the-thumb-on-the-track">Positioning the Thumb on the Track</h3>
<p>Let’s position the thumb on to the track.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.progress</span><span class="hljs-selector-pseudo">::before</span> {
  # rest of properties

    <span class="hljs-attribute">translate</span>: <span class="hljs-built_in">calc</span>((var(--radius) - <span class="hljs-built_in">var</span>(--track-offset)) * <span class="hljs-built_in">cos</span>(var(--angle)))
      <span class="hljs-built_in">calc</span>((var(--radius) - <span class="hljs-built_in">var</span>(--track-offset)) * <span class="hljs-built_in">sin</span>(var(--angle)));
}
</code></pre>
<p>This is probably the gnarliest piece of CSS in this entire article. It isn’t anywhere near as complex if we break it down in half. Here’s the first half:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">calc</span>((<span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--radius</span>) <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--track-offset</span>)) * <span class="hljs-selector-tag">cos</span>(<span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--angle</span>)))
</code></pre>
<p>This uses a little trigonometry to calculate the position of the thumb based on the current angle (which will be tied to the scroll progress) and the radius of the circle. The <code>cos()</code> function is used to determine the horizontal value of the position.</p>
<p>The second half of the value is identical, except we’re using the <code>sin()</code> function to determine the vertical position of the indicator:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">calc</span>((<span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--radius</span>) <span class="hljs-selector-tag">-</span> <span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--track-offset</span>)) * <span class="hljs-selector-tag">sin</span>(<span class="hljs-selector-tag">var</span>(<span class="hljs-selector-tag">--angle</span>)))
</code></pre>
<p><em>⚠️</em> I’m not going to use this article as an introduction into trigonometry, but I can point you in the direction of some amazing resources:</p>
<ul>
<li><a target="_blank" href="https://web.dev/articles/css-trig-functions">Trigonometric functions in CSS</a></li>
<li><a target="_blank" href="https://tympanus.net/codrops/2021/06/04/trigonometry-in-css-and-javascript-beyond-triangles/">Trigonometric functions in CSS and JavaScript: Beyond Triangles</a></li>
</ul>
<p>You may have noticed that I’ve specified a variable, <code>--angle</code>, that I haven’t yet defined. Because we’ll be animating the <code>--angle</code>, we need to explicitly define it using the <code>@property</code> rule, much like we did for the <code>--progress</code> property. The only difference is that we’ll need to specify a different syntax value. Instead of <code>&lt;percentage&gt;</code> the value will need to be <code>&lt;angle&gt;</code>:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@property</span> --angle {
    <span class="hljs-selector-tag">syntax</span>: '&lt;<span class="hljs-selector-tag">angle</span>&gt;';
    <span class="hljs-selector-tag">inherits</span>: <span class="hljs-selector-tag">false</span>;
    <span class="hljs-selector-tag">initial-value</span>: <span class="hljs-selector-tag">-90deg</span>;
}
</code></pre>
<p>By setting the initial value to <code>-90deg</code>, we ensure that the thumb is placed at the 12 o’clock position on the progress indicator.</p>
<p>Your indicator should now look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/positioned-thumb.png" alt="The thumb is positioned at the top center of the progress indicator" width="600" height="400" loading="lazy">
<em>Showing the thumb now on the track of the progress indicator</em></p>
<p>The next step is to create the animation for the thumb and then bind the animation timeline to the scroll position of the page.</p>
<h3 id="heading-animating-the-thumb-indicator">Animating the Thumb Indicator</h3>
<p>Let’s start by creating a new animation:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@keyframes</span> rotate {
    0% {
        <span class="hljs-attribute">--angle</span>: -<span class="hljs-number">90deg</span>;
    }

    100% {
        <span class="hljs-attribute">--angle</span>: <span class="hljs-number">270deg</span>;
    }
}
</code></pre>
<p>Over the course of the entire animation, the thumb will rotate 360 degrees, performing a full revolution over the progress element.</p>
<p>Finally we need to add the following two properties to the thumb:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.progress</span><span class="hljs-selector-pseudo">::after</span> {
    # other CSS properties

    <span class="hljs-attribute">animation</span>: rotate linear <span class="hljs-number">1ms</span>;
    <span class="hljs-attribute">animation-timeline</span>: <span class="hljs-built_in">scroll</span>(nearest block);
}
</code></pre>
<p>Doing so applies the rotate animation to our thumb and binds it to the scroll position.</p>
<p>Everything should now work flawlessly:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/thumb-complete.gif" alt="The completed progress indicator UI" width="600" height="400" loading="lazy">
<em>Final product showing the animation working smoothly as a user scrolls</em></p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>I created this progress indicator specifically to become more familiar with the amazing tools that CSS has shipped in the last couple years. Hopefully you learnt just as much from this lesson as I did making it.</p>
<p>There were other CSS features I wanted to explore, like <code>popover</code> and <code>:has</code> but I couldn’t find a way to fit them in with this animation. If you find this article interesting, I might try and create more little changes to the Component Odyssey platform, using cutting-edge CSS features.</p>
<p>By wary, because a lot of the CSS features I’ve covered are still very new. So you should check the browser support before using them in production. </p>
<p>If they’re not supported in one or more browsers, but you’re desperate to use them, then use a <strong>progressive enhancement</strong> strategy (as I went over in this tutorial) to ensure that those with compatible browsers get the full experience, while still offering users of unsupported browsers a solid baseline experience.</p>
<p>If you enjoyed this article, and would love to learn more about Component Odyssey or other cool web development tips, then consider <a target="_blank" href="https://component-odyssey.com/subscribe">subscribing to the newsletter</a>.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><a target="_blank" href="https://developer.chrome.com/docs/css-ui/scroll-driven-animations#getting_practical_with_scroll_progress_timelines">Getting practical with scroll progress timelines</a></li>
<li><a target="_blank" href="https://dev.to/afif/we-can-finally-animate-css-gradient-kdk">We can finally animate CSS gradients</a></li>
<li><a target="_blank" href="https://codepen.io/LukyVj/pen/rNqvowZ">Fitness inspired loaders</a></li>
<li><a target="_blank" href="https://drafts.css-houdini.org/css-properties-values-api-1/#at-property-rule">MDN: @property at-rule</a></li>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timeline">MDN: Animation Timeline</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Variables in Figma – A Handbook for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ At Figma Config 2023, the Figma team unveiled a lot of new features – including variables. The launch of variables in Figma offers designers a new approach that helps them make their designs more flexible and adaptable.  In this tutorial, you'll lear... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/variables-in-figma-handbook/</link>
                <guid isPermaLink="false">66d03a3ba30d09f91d49b78b</guid>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ figma ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Faith Olohijere ]]>
                </dc:creator>
                <pubDate>Fri, 15 Dec 2023 22:11:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/12/How-to-Use-Variables-in-Figma-cover--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>At Figma Config 2023, the Figma team unveiled a lot of new features – including variables. The launch of variables in Figma offers designers a new approach that helps them make their designs more flexible and adaptable. </p>
<p>In this tutorial, you'll learn what variables in Figma are, and how to create and implement different types of variables while designing in Figma.</p>
<h2 id="heading-prerequisites">Prerequisites:</h2>
<p>To get the most out of this handbook, it'll be helpful to have basic knowledge of how to use Figma and its features. But note that this is not necessary, as I wrote this handbook for everyone – irrespective of their individual level of knowledge. </p>
<p>This handbook is for everyone who is interested in learning more about variables, Figma, and design in general.</p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-variables">What are variables?</a></li>
<li><a class="post-section-overview" href="#heading-differences-between-variables-and-styles-in-figma">Differences between Variables and Styles in Figma</a></li>
<li><a class="post-section-overview" href="#heading-why-are-variables-important-to-the-design-process">Why are Variables Important to the Design Process?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-variables-in-figma">How to Create Variables in Figma</a><ul>
<li><a class="post-section-overview" href="#heading-how-to-create-colour-variables-in-figma">How to Create Colour Variables in Figma</a><ul>
<li><a class="post-section-overview" href="#heading-how-to-create-colour-variables-for-tokens">How to Create Colour Variables for Tokens</a></li>
<li><a class="post-section-overview" href="#heading-how-to-implement-colour-variables-in-your-designs">How to Implement Colour Variables in Your Designs</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-different-modes-with-variables">How to Create Different Modes with Variables</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-create-number-variables-in-figma">How to Create Number Variables in Figma</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-string-variables-in-figma">How to Create String Variables in Figma</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-boolean-variables-in-figma">How to Create Boolean Variable in Figma</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-use-variables-for-advanced-prototyping">How to Use Variables for Advanced Prototyping</a><ul>
<li><a class="post-section-overview" href="#heading-advanced-prototyping-with-number-variables">Advanced Prototyping with Number Variables</a></li>
<li><a class="post-section-overview" href="#heading-advanced-prototyping-with-boolean-variables">Advanced Prototyping with Boolean Variables</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-use-variables-for-developers-using-apis">How to Use Variables for Developers- Using APIs</a> </li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h1 id="heading-what-are-variables">What Are Variables?</h1>
<p>The word "variable" has a lot of definitions. The Oxford Dictionary defines the word variable as "not consistent or having a fixed pattern; liable to change." Another definition says "an element, feature, or factor that is liable to vary or change." </p>
<p>The definitions above simply tell us that variables are elements which are dynamic and prone to change. With these definitions, we can now define what a variable is in Figma. </p>
<p>In Figma, a variable stores reusable values like colour and text values that you can apply to different kinds of design properties and prototypes.</p>
<h2 id="heading-differences-between-variables-and-styles-in-figma">Differences between Variables and Styles in Figma</h2>
<p>Given the definition of variables above, you might have begun to see some similarities between variables and style guides. Although both features exist to make your work better, there are a few key differences to keep in mind:</p>
<ul>
<li>Variables are a more advanced feature, and they allow you to define and reuse values like colours, text, and spacing across your designs. On the other hand, styles are predefined sets of design properties such as text styles, colour styles, and effect styles.</li>
<li>Variables allow designs to change when used in various contexts, because of their dynamic nature, unlike styles. For example, you can change your designs from light mode to dark mode or have padding values change when designing for different devices. This makes variables useful for creating design systems with adaptable components.</li>
<li>Variables offer a more flexible design process in creating flexible design components, especially where you want to change values like button text or color on different instances of the same component. Styles are typically used for maintaining consistent design elements like button styles, text headings, or colour palettes.</li>
<li>Variables can store raw, single values, while styles store sets of values.</li>
</ul>
<h2 id="heading-why-are-variables-important-to-the-design-process">Why are Variables Important to the Design Process?</h2>
<p>Using variables is quite important for a number of reasons.</p>
<p>First, variables help maintain <strong>consistency</strong> across a design system. By defining variables for colors, typography, spacing, and other design elements, you ensure that these elements have a uniform appearance throughout your project. This consistency is crucial for branding and user experience.</p>
<p>Variables also make designs <strong>adaptable</strong>. Designers can quickly experiment with different values such as colour schemes or font sizes by adjusting the variables. This adaptability is valuable when creating designs for different platforms or devices.</p>
<p>Variables are also quite <strong>efficient</strong>. When a variable is updated, all instances of that variable in the design updates automatically. This saves time and effort, and eliminates the need to manually update every instance of a specific element.</p>
<p>Variables are particularly useful in large projects or design systems because of their <strong>scalability</strong> and <strong>ease of maintenance</strong>. They allow designers to scale their designs without losing control. </p>
<p>Since projects grow and design systems evolve over time, variables can be adjusted globally to accommodate new requirements. Variables also provide a central place to update these changes, ensuring that all design elements are consistently modified.</p>
<p>And finally, variables can be beneficial to developers during the <strong>hand-off process</strong>. Designers can provide developers with precise values for design elements, reducing the chances of misinterpretation and streamlining the implementation process. </p>
<h1 id="heading-how-to-create-variables-in-figma">How to Create Variables in Figma</h1>
<p>Variables are quite easy to create in Figma. Below, I'll walk you through the steps for creating different kinds of variables in Figma.</p>
<p>At the moment, we have four types of variables in Figma:</p>
<ul>
<li>Color: used for colour fills.</li>
<li>Number: used for dimensions, corner radius, and auto layout properties.</li>
<li>String: used for text layers and variant properties.</li>
<li>Boolean: used to toggle layer visibility.</li>
</ul>
<p>We'll create and implement each of these variables in Figma, and also use them for advanced prototyping.</p>
<h2 id="heading-how-to-create-colour-variables-in-figma">How to Create Colour Variables in Figma</h2>
<p>The first type of variable we'll be creating is a colour variable. As a designer or developer, you have likely used colours in your projects. So, the concept of colour shouldn't be unfamiliar to you from a design standpoint.</p>
<h3 id="heading-step-1-open-a-new-figma-file">Step 1: Open a new Figma file</h3>
<p>Let's assume that you want to create colour variables for a new design project you're going to start working on, like a magazine website for example. The first thing you need to do is open a new Figma file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Variable-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Blank Figma file</em></p>
<h3 id="heading-step-2-choose-a-colour-palette">Step 2: Choose a colour palette</h3>
<p>The next step is to choose a colour palette for the project. Every design project has a set of colours used repeatedly to establish consistency – for example, for headers and backgrounds, to call attention to a primary button, and so on. </p>
<p>You'll want to choose colours which complement each other for your design. If you need some help here, you can read my article on the <a target="_blank" href="https://www.freecodecamp.org/news/the-60-30-10-rule-in-design/">60-30-10 rule in design</a>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Variable-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a colour palette</em></p>
<h3 id="heading-step-3-create-variables-for-each-colour">Step 3: Create variables for each colour</h3>
<p>Next, we'll create variables for each colour code in the palette. Go to the panel on the right-hand side and click on <em>local variables</em>.</p>
<p>Local variables means all the variables located in the design file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click on local variables</em></p>
<p>Click on <em>create variable</em> to create the first variable in the file. </p>
<p>A dropdown will appear containing the four types of variables I explained earlier. Since we're trying to create colour variables in this section, we'll choose <em>color</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-5.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create a colour variable</em></p>
<p>A created variable section will come up, with two columns: the title of the variable (<em>Color</em>), and the value of the variable (the colour code-FFFFFF).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Variable-6.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choose colour variables</em></p>
<p>Give your new variable a name – you can use the role of the colour, primary background for instance. In the next column, type the colour code or use a colour picker. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-7.png" alt="Image" width="600" height="400" loading="lazy">
<em>Rename variable &amp; type in colour code</em></p>
<p>And there you go – you just created your first colour variable!</p>
<p>To see more editing options, hover over the variable's row. An <em>edit variable</em> icon will pop up.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-141.png" alt="Image" width="600" height="400" loading="lazy">
<em>Edit variable</em></p>
<p>Click on it to edit the colour variable to your taste.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-8.png" alt="Image" width="600" height="400" loading="lazy">
<em>Edit the colour variable/add a description</em></p>
<p>In the editing section, you can add a description on how to use the variable, hide from publishing, and so on.</p>
<p>Having done that, follow the steps above to create variables for the remaining colours in the colour palette.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-10.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create variables for other colours</em></p>
<p>You can also organise your variables into groups. To do this, select the colour variables you want to group (hold down SHIFT key), and right-click.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-11.png" alt="Image" width="600" height="400" loading="lazy">
<em>Group the colour variables</em></p>
<p>This will bring out some options:</p>
<ul>
<li>New group with selection</li>
<li>Edit variables</li>
<li>Duplicate variables</li>
<li>Delete variables</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-12.png" alt="Image" width="600" height="400" loading="lazy">
<em>New group with selection</em></p>
<p>Choose <em>New group with selection</em>, double-click on the group name, and rename it to <em>color/blue</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-14-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Rename group</em></p>
<p>You can group your colour variables anyway you'd like to – for example, background colours, header colours, different shades of a particular colour, and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-15.png" alt="Image" width="600" height="400" loading="lazy">
<em>Colour blue variables grouped.</em></p>
<p>Violà! You just created a colour variable group in Figma. Click on the collection drop-down and choose <em>rename collection</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-16.png" alt="Image" width="600" height="400" loading="lazy">
<em>Rename collection</em></p>
<p>You can rename this collection <em>primitives</em>. </p>
<p><em>Primitives</em> means basic. Also, you can decide to rename your collections or not. The choice rests on you.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-39.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed primitives collection</em></p>
<h3 id="heading-how-to-create-colour-variables-for-tokens">How to Create Colour Variables for Tokens</h3>
<p>Now, we'll create colour variables for the text, surfaces (such as backgrounds), and borders we need for the project. We want to assign different functions to the colour palette (variables) we created earlier.</p>
<p>Click on local variables and create a new collection. You can name this <em>tokens</em>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-21.png" alt="Image" width="600" height="400" loading="lazy">
<em>New collection</em></p>
<p>Create a new colour variable and rename it "primary text". </p>
<p>In order to save yourself time, and group your variables as you're naming them, rename the variable as <em>text/primary</em>. This will automatically form a group.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-24.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating and grouping text variables</em></p>
<p>Click on the fill box and go to <em>Libraries</em> to see all colour variables created.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-26.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assigning colour from libraries</em></p>
<p>We'll choose <em>Main Black</em> which is under <em>color/greys</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-27.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing colour black</em></p>
<p>We can go ahead and assign other colour variables for different text functions, as much as we want to. Remember to add <em>text/</em> before the actual name of the variable, so it'll form a group automatically.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-28.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assigning colour variables for text</em></p>
<p>Next, we'll create colour variables for surfaces such as backgrounds, and for borders as well.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-29.png" alt="Image" width="600" height="400" loading="lazy">
<em>Colour variables for surfaces and borders</em></p>
<p>Some of the colour variables might bear the same colour code, but they have different functions, so that's totally fine. For example, the colour code for button text is the same as the colour code for main background. </p>
<h3 id="heading-how-to-implement-colour-variables-in-your-designs">How to Implement Colour Variables in Your Designs</h3>
<p>Next, we're going to implement these colour variables in our design. </p>
<p>In the image below, there are four mobile wireframes with no colour and images (I created these previously). </p>
<p>You can read about how to create wireframes in this article: <a target="_blank" href="https://www.freecodecamp.org/news/what-is-wireframing/">What is Wireframing? How to move from Paper Sketches to High Fidelity Wireframes</a>.</p>
<p>We'll use the colour variables we've created to add colour to the buttons and text, making sure all elements are consistent.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-30.png" alt="Image" width="600" height="400" loading="lazy">
<em>Low-fidelity wireframes</em></p>
<p>Starting with the first screen, let's add colour to the button. Click on the button, and go to to <em>Fill</em> on the right-hand side of your screen. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-32-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click on button</em></p>
<p>In the <em>Fill</em> section, click on <em>style</em> (the four dot icon by the side). Selecting <em>style</em> will bring up a list of colours in your libraries. Select the colour you've assigned for the primary button in order to implement it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-33-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select a fill colour from the colour variables in libraries</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-34-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Implemented button colour</em></p>
<p>Next, give the button text a white colour following the same steps.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-35-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Implementing colour variable for button text</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-36-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Implemented button text colour</em></p>
<p>You can go ahead and do the same for the other screens, following the steps above. Don't forget to update the text and colours as well. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-37-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Updating colour variables for other screens</em></p>
<p>You can also add some images or illustrations to complete the look.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/variable-38-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding illustrations to updated design</em></p>
<p>Note: You can get your illustrations from plugins in Figma like Storyset by Freepik, Artify Illustrations, and so on, as well as from illustration libraries like <a target="_blank" href="https://www.freepik.com/">Freepik</a>, <a target="_blank" href="https://www.lapa.ninja/blog/free-illustrations-library-for-your-project/">Lapa Ninja</a>, and others.</p>
<h3 id="heading-how-to-create-different-modes-with-variables">How to Create Different Modes with Variables</h3>
<p>Next, we'll create different modes for our design. For instance, if you're working on a project that requires light and dark modes, instead of changing all the design elements manually to accommodate the modes, you can simply use variables to implement that.</p>
<p>To start with, click on <em>Local variables</em> to create a new variable. A list of all variables in the file and their groups will come up:</p>
<p>color/blue:</p>
<ul>
<li>Primary Button</li>
<li>Main Blue</li>
</ul>
<p>color/greys:</p>
<ul>
<li>Main Black</li>
<li>Main Background</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-142.png" alt="Image" width="600" height="400" loading="lazy">
<em>Opening "Local variables"</em></p>
<p>Next, I'll create a new collection so I can just focus on the modes I am about to create. To create a new collection, simply click on the menu icon on the variables header.</p>
<p>Note that creating a new collection isn't mandatory. It's just to help take your focus away from other variables you have already created.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-143.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new collection</em></p>
<p>Next, I'll rename the collection to <em>Modes.</em> To rename a collection, simply double-click on the title, and input your preferred title.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-144.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renaming a collection</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-145.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed collection "Modes"</em></p>
<p>Next, click on <em>Create variable</em> to create a new variable. I'll choose <em>Color</em> because that's the variable we're working with.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-146.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a variable called Color</em></p>
<p>The created colour variable will come up with a default colour code: FFFFFF.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-147.png" alt="Image" width="600" height="400" loading="lazy">
<em>Created color variable with default colour code: FFFFFF</em></p>
<p>Next, I'll rename the variable <em>Background</em> because I'm trying to set the background colours for each mode (light and dark).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-148.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed color variable: Background</em></p>
<p>Now, we've been working with only the name and value of the variables we've created, but we can add another column when we want to create modes. To do this, simply click on the plus icon on the header to add a new variable mode.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-149.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the plus icon</em></p>
<p>The new mode will come with three columns: </p>
<ul>
<li>Column 1 (the title of the variable – Background)</li>
<li>Mode 1 (the first value of the variable – colour code FFFFFF)</li>
<li>Mode 2 (the first value of the variable – colour code FFFFFF)</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-150.png" alt="Image" width="600" height="400" loading="lazy">
<em>Created new mode</em></p>
<p>Next, I'll rename the modes to light and dark. To do this, simply double-click on the title and edit the name.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-151.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed modes: Light &amp; Dark</em></p>
<p>Now, we'll assign a value to the background for dark mode. To do this, simply input the colour code/value you prefer for the background. I'll use #0C3272 as my background colour for dark mode.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-152.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changed value for dark mode background</em></p>
<p>Next, we'll create other colour variables for other elements like, text, button colour, button text colour, and so on for the two modes. I''ll list out the specifications to make it easier:</p>
<p><strong>Light/Dark:</strong></p>
<ul>
<li>Body text: 1A1A1A/FFFFFF</li>
<li>Button: 0C3272/FFFFFF</li>
<li>Button text: FFFFFF/0C3272</li>
<li>iPhone header: 1A1A1A/FFFFFF</li>
</ul>
<p>Next, we'll go ahead to create the variables. Just follow the steps we followed earlier to create the variables and assign values for each of the modes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-154.png" alt="Image" width="600" height="400" loading="lazy">
<em>Created variables for other elements</em></p>
<p>Next, we make sure the design is connected to the variables we created. To do this, simply hold the element and use <em>Fill</em> to tie it to the colour variable. </p>
<p>For the Button text for instance, select the text, and click on the style icon in <em>Fill</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-155.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on style icon in the "FFill" section</em></p>
<p>Next, scroll down the list that comes up, to the specific variable you want to tie the variable to (in this case Body text).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-156.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting Body text variable.</em></p>
<p>Do the same for the other elements in the design, including the background.</p>
<p>Note that I'll be leaving the illustrations the way they are.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-157.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screens connected to the variable modes.</em></p>
<p>To check if the modes actually work, click on the <em>change variable mode</em> icon on the <em>Layer</em> section on the right-hand panel of your screen. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-158.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the "change variable mode" icon</em></p>
<p>A list of all modes (Light &amp; Dark) will come up and you can switch the screen to whatever mode you choose.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-159.png" alt="Image" width="600" height="400" loading="lazy">
<em>Switching modes</em></p>
<p>A section named <em>Modes</em> will appear on the <em>Layer</em> section, indicating that one of the screens is in dark mode.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-160.png" alt="Image" width="600" height="400" loading="lazy">
<em>One dark mode &amp; one light mode screen.</em></p>
<h2 id="heading-how-to-create-number-variables-in-figma">How to Create Number Variables in Figma</h2>
<p>Next, I'll show you how to create number variables in Figma. </p>
<p>Number variables are defined by number values, and they can be applied to corner radius, width or height padding, and so on. Here are the steps to follow to create your own:</p>
<h3 id="heading-step-1-choose-a-variable">Step 1: Choose a variable</h3>
<p>Just like we did when creating color variables, click on the local variables panel to select the kind of variable you're trying to create. Here, you'll select <em>number.</em> </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/variable-40.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing variable to create</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Variable-41.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting "number"</em></p>
<p>When you select <em>number</em>, it appears on the list of variables with a value, in this case 0. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-43.png" alt="Image" width="600" height="400" loading="lazy">
<em>Number variable showing Number with a default value of 0</em></p>
<p>Now, you can rename the number variable to whatever you decide. To rename the variable, double click on <em>number</em>, and change it to whatever name you want.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-44.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renaming number variable</em></p>
<p>I'll rename mine to <em>OrderCount,</em> because I'm trying to implement a function that allows a user to increase the number of portions of food they're trying to order.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-45.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamed number variable</em></p>
<p>Next, we'll set the default number value to <em>1</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-46.png" alt="Image" width="600" height="400" loading="lazy">
<em>Setting default number value</em></p>
<p>Now we'll tie the number on the design to the number variable (<em>OrderCount).</em> To do this, click on the number in the design.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-47.png" alt="Image" width="600" height="400" loading="lazy">
<em>Implementing the number variable</em></p>
<p>Then go to <em>Text</em> on the left hand side of your screen. Click on the <em>Apply variable</em> icon to apply the variable.</p>
<p>Note: The <em>apply variable</em> icon will only appear on the <em>Text</em> section when a variable has been created.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-49.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the "appy variable" icon</em></p>
<p>Clicking on the icon will bring up a list of all number variables available in the file. Next, you'll select the variable you're trying to implement. I'll choose <em>OrderCount</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-50.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting a number variable</em></p>
<p>When the variable has been implemented (tied to the number), it'll appear on the text section, indicating that a number variable has been implemented.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-51.png" alt="Image" width="600" height="400" loading="lazy">
<em>Implemented number variable</em></p>
<p>Now, we'll also need two more number variables for the other number values in the design (cost of food and total cost). This is so that these values will also change when a user increases the number of portions they're ordering. </p>
<p>We won't include delivery fee, because it remains the same way irrespective of the number of portions a user orders.</p>
<p>Next, we'll follow the same process as we did above to create number variables for these.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-52.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating other number variables</em></p>
<p>Next, we'll tie the numbers in the design to their respective number variables, just as we also did earlier. </p>
<p>Note: In the main design, I gave the actual number (25) a different frame from the dollar sign (which is in text). This is because when creating the number variable, the dollar sign will not be attached, because it's a word, not a number. </p>
<p>Consequently, when I tie the number variable to the design, I'll be applying it to the frame containing the number alone.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-53.png" alt="Image" width="600" height="400" loading="lazy">
<em>Give the number a different frame from the dollar sign</em></p>
<p>So, when I tied the first number to the number variable I created (Cost-Portion), something interesting happened. The number in the design took on the value of the variable. Instead of 25.00 which was in the screen earlier, it changed to just 25 because that's what the number variable was set to. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-55.png" alt="Image" width="600" height="400" loading="lazy">
<em>Number variable changing the number in the design</em></p>
<p>Now, to avoid any unpleasantness, I'll change the values of the other numbers, and realign them.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-56.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changed and realigned number values in the design</em></p>
<p>We've just created number variables for our design. In the section for advanced prototyping, we'll check to see if these number variables actually work.</p>
<h2 id="heading-how-to-create-string-variables-in-figma">How to Create String Variables in Figma</h2>
<p>Next, you'll learn how to create string variables in Figma.  </p>
<p>As I wrote earlier, string variables are used for text layers and variant properties. With string variables, you can change the headings in your design, flip text on different screens, change language modes, and so on.</p>
<p>For this article, we'll use string variables to change the headings on the screens for each mode we created earlier (light and dark). </p>
<p>As usual, our first step is to click on <em>Local variables</em> and select the type of variable we want to create.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-161.png" alt="Image" width="600" height="400" loading="lazy">
<em>Going to local variables to create a new variable</em></p>
<p>I'll choose <em>String</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-163.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing "String" out of a list of all variables</em></p>
<p>When I do that, the string variable I just created will appear on the list of variables.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-164.png" alt="Image" width="600" height="400" loading="lazy">
<em>Created String variable</em></p>
<p>If you noticed, the string variable has two columns for "string value", because I created the variable in the <em>Modes</em> collection. Following that, let's see if we can change the headings for each mode. </p>
<p>Note: The string value is the actual text you're trying to change. </p>
<p>So, for the first screen whose heading is "Transactions Made Easy", I want it to change to "Easy Transactions, Less Stress" for dark mode. For the second screen whose heading is "Pay Bills with Ease", I want it to change to  "Paid Bills, Easier Life" for dark mode.</p>
<p>Since we're changing the headings for two different screens, we'll create another string variable.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-165-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating another string variable</em></p>
<p>Next, we'll input the different values for the different modes. To do this, just input the different texts for the two screens in both modes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-166-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Inputing string value</em></p>
<p>Next, we'll tie the headings to the string variables we just created. To do this, click on the particular heading, and go to the <em>Apply variable</em> icon on the <em>Text</em> section.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-167-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Applying string variable</em></p>
<p>Next, scroll down and choose the string you're applying it to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-168-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing string variable</em></p>
<p>Once you're done, a string icon will come up, indicating that a string variable was applied to the text.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-169-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Applied string variable</em></p>
<p>Do the same for the second string:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-170-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Applying string variable to the second screen</em></p>
<p>Next, let's test to see if the string variable works. Select the screens which have the applied variable, go to <em>Layers,</em> and change the mode from light to dark.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-171-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting screens which have the applied variables</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-172-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting dark mode</em></p>
<p>Mine works:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-173-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screens changed to dark mode</em></p>
<h2 id="heading-how-to-create-boolean-variables-in-figma">How to Create Boolean Variables in Figma</h2>
<p>Next up, we'll learn how to create Boolean variables. </p>
<p>Generally, boolean variables are variables that can only have two possible values – true or false. In Figma, boolean variables have the same function: they are used for variant properties or components with two values: true or false. </p>
<p>Remember the toggle in the design above? </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-110.png" alt="Image" width="600" height="400" loading="lazy">
<em>Toggle in the design used for implementing number variables</em></p>
<p>I'll change that to a checkbox and use boolean variables to make it work. </p>
<p>To do this, I'll copy out the component and paste it on another frame. I'll then add the checkbox (and replace it in the main design screen later).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-111.png" alt="Image" width="600" height="400" loading="lazy">
<em>Checkbox on a blank frame.</em></p>
<p>Next, we'll make the selection a variant. To do this, double-click on the <em>Create component</em> icon on your Figma file header.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-113.png" alt="Image" width="600" height="400" loading="lazy">
<em>Double-clicking on "create component" icon</em></p>
<p>A variant will automatically appear:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-114.png" alt="Image" width="600" height="400" loading="lazy">
<em>Variant of the component</em></p>
<p>Next, I'll create different states for the checkboxes: default, hover, and filled.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-116.png" alt="Image" width="600" height="400" loading="lazy">
<em>Different states for the chechboxes: Default, hover and filled.</em></p>
<p>Now, we'll create the boolean variable. </p>
<p>To do this, go to <em>Local variables</em> as usual and select <em>Boolean</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-118.png" alt="Image" width="600" height="400" loading="lazy">
<em>Opening local variables</em></p>
<p>Click on <em>Create variable</em>. </p>
<p>Next, we'll choose <em>Boolean</em> from the list.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-117.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing "boolean" from the list</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-119.png" alt="Image" width="600" height="400" loading="lazy">
<em>Created boolean variable</em></p>
<p>Next, we'll rename the boolean variable <em>SaveFood</em> since we're trying to create a function for saving a food choice for subsequent orders.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-120.png" alt="Image" width="600" height="400" loading="lazy">
<em>Renamied boolean variable</em></p>
<p>Next, we'll make the variable <em>True</em> by default. To do this, just click on the toggle icon by the side of the variable.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-121.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You've created a boolean variable!</p>
<p>We'll create an interaction for this boolean variable in the advanced prototyping section and check if it works. </p>
<h2 id="heading-how-to-use-variables-for-advanced-prototyping">How to Use Variables for Advanced Prototyping</h2>
<p>In this section, we'll learn how to use variables for advanced prototyping in Figma, using the colour, number, string, and boolean variables we implemented earlier in the design.</p>
<p>N.B: You can only use advanced prototyping features on Figma if your file is on a paid team file. If you don't have a paid team version, you can apply for the <em><a target="_blank" href="https://www.figma.com/education/">Figma for Education</a></em> plan. It's a way Figma helps learners and educators by giving them access to resources, and all benefits of a paid version, for free.</p>
<p>You can use advanced prototyping when you have a lot of screens to work on, and to simply make prototyping easier.</p>
<h3 id="heading-advanced-prototyping-with-number-variables">Advanced Prototyping with Number Variables</h3>
<p>Starting with the number variables we created above, let's try to check if it actually works. But before we do that, we'll have to actually prototype the design. </p>
<p>Note that you can prototype number variables for designs where your user can increase or decrease the number of an item on the screen. Prototyping helps to show the functionality and how that particular feature would work. </p>
<p>To start with, I'll make the frame where the order count is a component. To do this, select the frame, and click on the component icon on your Figma file header.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-57.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting the order count frame</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-58.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the component icon</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-59.png" alt="Image" width="600" height="400" loading="lazy">
<em>The order count component</em></p>
<p>Click on the component icon again to make it a variant.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-60.png" alt="Image" width="600" height="400" loading="lazy">
<em>Making the order count component a variant</em></p>
<p>I'll make a frame outside the screen and drag the variant there, so I'll be able to work on the interactions well.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-61.png" alt="Image" width="600" height="400" loading="lazy">
<em>Making a frame outside the screen</em></p>
<p>Remember that we want to implement a function where the number of portions increases when the user clicks on the plus icon. </p>
<p>We'll start prototyping from here. </p>
<p>Now, click on the plus icon in the default variant and move to the prototype tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-62.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the plus icon in the default variant</em></p>
<p>Next, click on the plus icon in the interactions area to add an interaction.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-63.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding an interaction</em></p>
<p>A tab will come up showing interactions. In this case, it's set to default <em>On click</em>, and no interaction has been added yet (None).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-64.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding an interaction</em></p>
<p>Now, click on the dropdown icon that says <em>None.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-65.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the dropdown icon</em></p>
<p>It'll bring up a list:</p>
<ul>
<li>Navigate to</li>
<li>Change to</li>
<li>Back</li>
<li>Set variable</li>
<li>Conditional</li>
<li>Scroll to</li>
<li>Open link</li>
<li>Open overlay</li>
<li>Swap overlay</li>
<li>Close overlay</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-66.png" alt="Image" width="600" height="400" loading="lazy">
<em>List following the dropdown</em></p>
<p>Choose <em>Set variable</em>. </p>
<p>A list of all variables in the file will come up, and you can then select the particular variable you want to implement. I'll click on <em>OrderCount</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-67.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing "set variable"</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-68.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on Order Count (the first time)</em></p>
<p>Next, I'll click on <em>OrderCount</em> again to write a mathematical expression, and all the available mathematical expressions will appear:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-69.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on Order Count (the second time) and showing all mathematical expressions</em></p>
<p>I'll select <em>Addition</em>, because that's what we're trying to do.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-70.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing the "addition" expression</em></p>
<p>You'll notice that an addition icon popped up to signify that the addition expression was given. </p>
<p>Next, I'll input <em>1</em> by the side of the addition icon to show that it's plus 1.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-71.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding number 1 to the expression</em></p>
<p>Done! </p>
<p>Now, we'll follow the same steps to do the same for the minus icon, making the expression subtraction instead of addition.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-72.png" alt="Image" width="600" height="400" loading="lazy">
<em>Added interactions for the minus icon</em></p>
<p>Done!</p>
<p>Note: We don't really need the variant we created earlier. You might only use the variant in cases where you want to create a hover state. I just wanted to show you how easy it would be to create a variant while doing this. </p>
<p>Next, we'll just copy the prototyped component and put it back in the main design.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-73.png" alt="Image" width="600" height="400" loading="lazy">
<em>Frame containing the prototyped variable</em></p>
<p>To put the prototyped component in the main design, click on <em>Assets</em> at the top of the left hand panel.</p>
<p>This section will show all the assets in the page you're currently on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-74.png" alt="Image" width="600" height="400" loading="lazy">
<em>Showing all assets on the page</em></p>
<p>Next, I'll drag the frame to the design. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-75.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dragged asset to main design</em></p>
<p>Note: If you don't want to follow the process above to place the prototyped component in the design, simply copy the component (CTRL + C), and <em>paste to replace</em> the frame on the main design.</p>
<p>Now, let's check our prototype out. To do this, you don't need to open the prototype on another tab. You can simply click on the asset and press SHIFT + space bar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-76.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicked asset</em></p>
<p>Another frame will appear on your screen. It's interactive and you can test your prototype on it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-77.png" alt="Image" width="600" height="400" loading="lazy">
<em>Interactive frame on your Figma screen.</em></p>
<p>Try clicking on the minus and plus icons on the frame to see if it carries out its function. </p>
<p>After checking the prototype, I'd like to implement some logic. </p>
<p>We don't want a scenario where the clicking on the minus icon continues till after 0 and now gives us a negative sign like -1 as you can see in the image below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-78.png" alt="Image" width="600" height="400" loading="lazy">
<em>Minus icon giving us negative values</em></p>
<p>That wouldn't make sense, so we'll add a <em>conditional</em>. </p>
<p>A conditional is simply a condition that sets rules about how the interaction should work.</p>
<p>To do this, I'll move to the frame containing the component I made earlier. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-79.png" alt="Image" width="600" height="400" loading="lazy">
<em>Frame containing prototyped component</em></p>
<p>I'll be adding the conditional to the minus icon since that's the area that would give us negative values. So, I want the values to stop at 1 since that's the least a user can order (they can't order half or 0, for example). </p>
<p>So, we'll just zoom into the component to add our conditional. Make sure you're on the prototype tab as well.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/variable-80.png" alt="Image" width="600" height="400" loading="lazy">
<em>Moving to prototype tab and zooming in on the prototyped component</em></p>
<p>I'll click on the variable icon by the minus frame.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-81.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting the variable icon close to the minus icon frame</em></p>
<p>This will bring up the already set interactions:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-82.png" alt="Image" width="600" height="400" loading="lazy">
<em>Already made interactions on the minus frame</em></p>
<p>Next, I'll click on the plus icon by the 'x' on the interactions header.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-83.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the plus icon in the interaction header</em></p>
<p>I'll choose <em>conditional</em> from the list of options which will appear:</p>
<ul>
<li>Navigate to</li>
<li>Change to</li>
<li>Back</li>
<li>Set variable</li>
<li>Conditional</li>
<li>Scroll to</li>
<li>Open link</li>
<li>Open overlay</li>
<li>Swap overlay</li>
<li>Close overlay</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-84.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing conditional from the list of options</em></p>
<p>We'll then write the condition. To do this, click on <em>Write condition</em> by the <em>if else</em> statement<em>.</em> </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-86.png" alt="Image" width="600" height="400" loading="lazy">
<em>Writing a condition for the interaction</em></p>
<p>When we click on <em>Write condition</em>, a list of all number variables will come up. I'll choose <em>OrderCount</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-87.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting ordercount</em></p>
<p>This will bring up a list of all available conditions:</p>
<ul>
<li>Equal to</li>
<li>Not equal to</li>
<li>Greater than</li>
<li>Greater than or equal to</li>
<li>Less than</li>
<li>Less than or equal to</li>
</ul>
<p>I'll choose <em>Not equal to</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-88.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing "Not equal to" condition</em></p>
<p>Next, the icon for the condition I chose will appear on the input field for writing the condition.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-89.png" alt="Image" width="600" height="400" loading="lazy">
<em>Condition appearing on the input field</em></p>
<p>Next, I'll input 0, which means the interaction is not equal to 0.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-90.png" alt="Image" width="600" height="400" loading="lazy">
<em>Inputing 0 (zero)</em></p>
<p>Next, I'll close the frame and try moving the <em>Set variable</em> section under the <em>conditional section</em> in the interaction. To close the Set variable section, click on the little dropdown icon.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-91.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the dropdown icon to close set variable</em></p>
<p>When you click on the little dropdown icon, the <em>Set variable</em> section will be minimized, allowing you move the section under the <em>Conditional</em> section.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-92.png" alt="Image" width="600" height="400" loading="lazy">
<em>Closed set variable section</em></p>
<p>Next, I'll drag the <em>set variable</em> section under the <em>conditional</em> section. To do this, just hover on the <em>set variable</em> section and use your trackpad or mouse to drag it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-93.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dragging set variable under conditional</em></p>
<p>We just added a conditional to our interaction! The icon for the minus frame will change to a condition icon, showing that a conditional has been added.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-94.png" alt="Image" width="600" height="400" loading="lazy">
<em>Added a conditional to minus interaction</em></p>
<p>Now, you can test this new interaction to see how it works. </p>
<p>Mine certainly does! It doesn't go lower than 0 anymore.</p>
<h3 id="heading-how-to-implement-cost-per-portion-variable">How to implement cost per portion variable</h3>
<p>Now, we want the other number values (cost per portion and total cost) to increase in response to the number of portions a user orders.</p>
<p>We'll start with the Plus icon frame:</p>
<p>Going back to the component we've been working on...</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-95.png" alt="Image" width="600" height="400" loading="lazy">
<em>Frame with prototyped component</em></p>
<p>I'll click on the plus frame and go ahead to <em>set variable</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-96.png" alt="Image" width="600" height="400" loading="lazy">
<em>Opening the interactions for plus frame</em></p>
<p>I'll click on the plus icon on the interactions header.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-97.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the plus icon on the interactions header</em></p>
<p>Next, I'll select <em>set variable</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-98.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting set variable</em></p>
<p>A list of all variables that have been created in the file will come up:</p>
<ul>
<li>The color variables for text, buttons, headings, and so on.</li>
<li>Number variables – <em>OrderCount</em>, <em>Cost-Portion</em>, and so on.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-99.png" alt="Image" width="600" height="400" loading="lazy">
<em>A list of all variables in the file</em></p>
<p>I'll scroll down to choose <em>cost-portion,</em> which is the cost per food portion a user orders.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-100.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing "Cost-portion" (the first time)</em></p>
<p>An input field to write an expression for the variable will come up.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-101.png" alt="Image" width="600" height="400" loading="lazy">
<em>Write expression input filed</em></p>
<p>To write an expression, click on Cost-Portion again and select <em>Addition</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-102.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing cost-portion (the second time) and selecting addition</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-104.png" alt="Image" width="600" height="400" loading="lazy">
<em>Addition icon coming up on input field</em></p>
<p>Next, I'll input 25, meaning that +25 should be added for every portion of food a user orders.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-103.png" alt="Image" width="600" height="400" loading="lazy">
<em>Inputing 25</em></p>
<p>Having added the interaction for the plus frame, we'll follow the same process for the minus frame. When you're done, the <em>Set variable</em> section should be under the <em>Conditional</em> section.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-105.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding interaction for the minus frame</em></p>
<p>Remember there's a conditional for the minus frame, so I'll just drag the new interaction inside the conditional.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-106.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dragging the new "set variable" interaction inside the conditiona;</em></p>
<p>Now, try testing the new interaction you just added. Mine certainly works!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-107.png" alt="Image" width="600" height="400" loading="lazy">
<em>Testing the new interaction</em></p>
<p>Next, we still have one last variable to add (Total Cost). </p>
<p>Follow the steps above to recreate this interaction. Starting with the plus frame, implement the variable to make sure $25 adds when the order increases. It should show a placeholder – <em>Total Cost + 25</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-108.png" alt="Image" width="600" height="400" loading="lazy">
<em>Implementing Total Cost variable</em></p>
<p>Now, do the same for the minus frame and test the interaction. Don't forget to add the new interaction inside the conditional.</p>
<p>Mine works!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-109.png" alt="Image" width="600" height="400" loading="lazy">
<em>Testing the interactions</em></p>
<p>You just learnt how to implement number variables with advanced prototyping in Figma. Congrats!</p>
<h3 id="heading-advanced-prototyping-with-boolean-variables">Advanced Prototyping with Boolean Variables</h3>
<p>Next, we'll create an interaction for the boolean variable we created earlier in the article. </p>
<p>Note that you can prototype your boolean variables in designs where you have features like checkboxes and toggles. The prototype would show how the checkbox is supposed to function.</p>
<p>To create the interaction, move to the prototype tab and focus on the frame containing the boolean components.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-122.png" alt="Image" width="600" height="400" loading="lazy">
<em>Frame containing boolean components</em></p>
<p>Now, our main interaction will start from the hover state because that's when a user tries to click on the checkbox. But we still need to add an action that will take the user from the default state to the hover state. </p>
<p>To do this, I'll just click on the first variant and drag it to the second variant.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-132.png" alt="Image" width="600" height="400" loading="lazy">
<em>Connecting first variant to the second variant</em></p>
<p>I'll change <em>On-click</em> to <em>While Hovering</em>. To do this, just click on the <em>On-click</em> dropdown and select from the list that pops up:</p>
<ul>
<li>On click</li>
<li>On drag</li>
<li>While hovering</li>
<li>While pressing</li>
<li>Key/Gamepad</li>
<li>Mouse enter</li>
<li>Mouse leave</li>
<li>Mouse down</li>
<li>Mouse up</li>
<li>After delay</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-133.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the on-click dropdown</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-134.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting "while hovering" from the list</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-135.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selected "while hovering"</em></p>
<p>I also want to change <em>Instant</em> to <em>Smart Animate</em>, so I'll click on the dropdown icon by <em>Instant</em>, and select from the list that appears:</p>
<ul>
<li>Instant</li>
<li>Dissolve</li>
<li>Smart animate</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-136.png" alt="Image" width="600" height="400" loading="lazy">
<em>Changing "Instant" to "Smart Animate"</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-137.png" alt="Image" width="600" height="400" loading="lazy">
<em>How the interaction looks</em></p>
<p>So, we're done with the first interaction and we'll get started on connecting the second variant to the third variant (Hover - Filled).</p>
<p>Just as we did earlier, we'll just drag the second variant to the third variant.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-124.png" alt="Image" width="600" height="400" loading="lazy">
<em>Connecting the second to the third variant</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-125-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>How the interaction looks</em></p>
<p>Like I said earlier, the main interaction starts from the second variant so we'll not be following the same steps we took to add the first interaction.</p>
<p>To continue, I'll click on the plus icon on the interaction header to add an action, and select <em>Set variable</em> from the list that pops up:</p>
<ul>
<li>Navigate to</li>
<li>Change to</li>
<li>Back</li>
<li>Set variable</li>
<li>Conditional</li>
<li>Scroll to</li>
<li>Open link</li>
<li>Open overlay</li>
<li>Swap overlay</li>
<li>Close overlay</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-126.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the plus icon on the interaction</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-127.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing "set variable" from the list</em></p>
<p>Next, I'll click on <em>Pick target variable</em> to select the boolean variable.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-128.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on "pick target variable"</em></p>
<p>I'll scroll down the list of variables to choose the variable I want: SaveFood.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-129.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting "SaveFood" variable</em></p>
<p>Now, to write the expression for this variable, we're going to say the value will be equal to true. So, I'll select <em>True</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-130.png" alt="Image" width="600" height="400" loading="lazy">
<em>Writing the expression and selecting "true"</em></p>
<p>Having selected <em>True</em>, the expression (<em>true</em>) will go under the <em>SaveFood</em> variable, indicating that an expression was applied.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-131.png" alt="Image" width="600" height="400" loading="lazy">
<em>How the interaction looks</em></p>
<p>Next, we'll just copy the original component and paste it in our design so it can sync when we're checking the prototype.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-138.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pasting the default component in the main design</em></p>
<p>To check the prototype directly on your Figma page, click on Shift + space bar.</p>
<p>Mine works!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-139.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>But I noticed something; I can't un-check the checkbox. No interaction was provided for that. Now, we'll quickly add that interaction so our component works perfectly. </p>
<p>To do this, we'll go back to our components, making sure we're in prototype mode, and drag the connection from filled all the way back to default.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Variable-140.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dragging the connection from filled state to default state</em></p>
<p>Now, it's works perfectly!</p>
<h2 id="heading-how-to-use-variables-for-developers-using-apis">How to Use Variables for Developers – Using APIs</h2>
<p>Variables are very helpful for teams consisting of developers and/or designers. </p>
<blockquote>
<p>Variables are now supported in Figma’s Plugin API—for building plugins and widgets—and in the REST API. Since variables is currently in open beta, features and functions may change as we respond to feedback. – Figma Docs</p>
</blockquote>
<p>There are three documentations which contain support for variables for developers on Figma: </p>
<ul>
<li>For the <a target="_blank" href="https://www.figma.com/developers/api#variables">REST API</a>: </li>
</ul>
<blockquote>
<p>This API includes endpoints for querying, creating, updating, and deleting variables. – Figma docs</p>
</blockquote>
<p>To be able to use this API, you must be a member of an enterprise.</p>
<ul>
<li>For the <a target="_blank" href="https://www.figma.com/plugin-docs/working-with-variables/">plugin API</a>: </li>
</ul>
<blockquote>
<p>This API provides support for creating and reading variables, and binding variables to components. – Figma docs</p>
</blockquote>
<ul>
<li>For the <a target="_blank" href="https://www.figma.com/widget-docs/working-with-variables/">widget API</a>: This API is connected to the plugin API. It is available to widgets by using the Plugin API the widget contains. </li>
</ul>
<p>Widgets are interactive elements that can be used to create interactive prototypes. Widgets extend the functionality of design files and FigJam boards and are often part of the larger design system, which is a collection of reusable components.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Variables exist in Figma to make your designs better. They are easy to use and create, and are helpful in every design project. In order to save yourself time, make sure to incorporate variables into your design process. </p>
<p>The key is to practice and explore, and you'll get better as you go. </p>
<p>Thank you for reading this article, I hope you enjoyed it! </p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
