<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mattia Astorino</title>
    <description>The latest articles on DEV Community by Mattia Astorino (@equinusocio).</description>
    <link>https://dev.to/equinusocio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F51866%2F4869b2ed-9745-434c-badf-9504fe150e7b.jpg</url>
      <title>DEV Community: Mattia Astorino</title>
      <link>https://dev.to/equinusocio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/equinusocio"/>
    <language>en</language>
    <item>
      <title>AI skills are the new NPM packages</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Fri, 03 Apr 2026 06:54:28 +0000</pubDate>
      <link>https://dev.to/equinusocio/ai-skills-are-the-new-npm-packages-1cb1</link>
      <guid>https://dev.to/equinusocio/ai-skills-are-the-new-npm-packages-1cb1</guid>
      <description>&lt;p&gt;&lt;strong&gt;We used to share code. Now we share intent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For years, our industry has been built around one core idea: reuse.&lt;br&gt;&lt;br&gt;
npm packages, shared libraries, frameworks — all ways to take someone else's solution and plug it into our own system.&lt;/p&gt;

&lt;p&gt;It worked. It scaled. It shaped how we build software.&lt;/p&gt;

&lt;p&gt;But there's always been a hidden cost.&lt;/p&gt;

&lt;p&gt;When you import a package, you're not just importing functionality — you're importing decisions.&lt;br&gt;&lt;br&gt;
Architecture choices, naming conventions, constraints, trade-offs made by someone else, often in a different context.&lt;/p&gt;

&lt;p&gt;Sometimes that's exactly what you want.&lt;br&gt;&lt;br&gt;
Other times, it's friction you carry for the lifetime of your product.&lt;/p&gt;




&lt;h2&gt;
  
  
  From code to knowledge
&lt;/h2&gt;

&lt;p&gt;I've been thinking about this a lot lately, especially with the rise of AI in our workflows.&lt;/p&gt;

&lt;p&gt;And I keep coming back to the same idea: &lt;strong&gt;AI skills are becoming the new npm packages.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But instead of distributing opinionated implementations, we're starting to distribute something more flexible — and arguably more valuable: &lt;strong&gt;expertise&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An AI skill doesn't give you code to reuse.&lt;br&gt;&lt;br&gt;
It gives you a way to think.&lt;/p&gt;

&lt;p&gt;It captures how someone approaches a problem — the constraints they consider, the trade-offs they make, the patterns they recognize — without forcing you into a specific stack or architecture.&lt;/p&gt;

&lt;p&gt;That's a very different kind of abstraction.&lt;/p&gt;

&lt;p&gt;We're moving from sharing &lt;strong&gt;solutions&lt;/strong&gt; to sharing &lt;strong&gt;reasoning&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this shift matters
&lt;/h2&gt;

&lt;p&gt;With traditional packages, reuse comes with coupling.&lt;/p&gt;

&lt;p&gt;You gain speed, but you inherit structure, opinions, and implementation.&lt;/p&gt;

&lt;p&gt;With AI skills, the relationship flips.&lt;/p&gt;

&lt;p&gt;You still benefit from someone else's experience, but you stay in control of the implementation. The output adapts to your context — your codebase, your constraints, your product.&lt;/p&gt;

&lt;p&gt;This decoupling is subtle, but powerful.&lt;/p&gt;

&lt;p&gt;It means that expertise becomes portable in a way it never really was before.&lt;/p&gt;

&lt;p&gt;Not as blog posts.&lt;br&gt;&lt;br&gt;
Not as documentation.&lt;br&gt;&lt;br&gt;
But as something you can actually use in your daily work.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this looks like in design systems
&lt;/h2&gt;

&lt;p&gt;This shift becomes very real when you look at design systems.&lt;/p&gt;

&lt;p&gt;Traditionally, a design system is distributed as a set of components, core elements, and guidelines. You build a system, document it, and teams consume it.&lt;/p&gt;

&lt;p&gt;The true value of a design system lies not simply in the sum of its individual parts.&lt;br&gt;&lt;br&gt;
It's the decisions behind them.&lt;/p&gt;

&lt;p&gt;Why a component behaves a certain way.&lt;br&gt;&lt;br&gt;
Why a pattern exists.&lt;br&gt;&lt;br&gt;
When to use it — and when not to.&lt;/p&gt;

&lt;p&gt;Those things are hard to encode in code, and this is where AI skills start to change the game.&lt;/p&gt;

&lt;p&gt;Imagine a design system not just as a static library, but as a skill you can query.&lt;/p&gt;

&lt;p&gt;Instead of browsing documentation, a developer could ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Generate a table component API consistent with our system, including accessibility constraints and edge cases."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of manually reviewing UI, you could run a skill that analyzes a screen and flags inconsistencies with your design tokens, spacing rules, or interaction patterns.&lt;/p&gt;

&lt;p&gt;Instead of onboarding someone through pages of docs, you could have a skill that explains your system in context — why things are built the way they are, not just what exists.&lt;/p&gt;

&lt;p&gt;In all these cases, you're no longer distributing just the output of the system.&lt;br&gt;&lt;br&gt;
You're distributing the thinking behind it.&lt;/p&gt;




&lt;h2&gt;
  
  
  A different kind of reuse
&lt;/h2&gt;

&lt;p&gt;What's interesting is that this doesn't replace traditional systems — it complements them.&lt;/p&gt;

&lt;p&gt;You still need components.&lt;br&gt;&lt;br&gt;
You still need code.&lt;/p&gt;

&lt;p&gt;But now there's another layer on top: a layer where knowledge itself becomes reusable.&lt;/p&gt;

&lt;p&gt;And that changes the nature of what we build and share.&lt;/p&gt;

&lt;p&gt;As someone working in UI and design systems, this feels particularly relevant.&lt;/p&gt;

&lt;p&gt;Because so much of the work has always been about decisions, consistency, and trade-offs — things that don't live comfortably in code alone.&lt;/p&gt;

&lt;p&gt;AI skills give us a way to package that part of the work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Not without risks
&lt;/h2&gt;

&lt;p&gt;Of course, this isn't automatically better.&lt;/p&gt;

&lt;p&gt;A poorly designed skill can be just as harmful as a poorly designed library — maybe even more, because it's less visible.&lt;/p&gt;

&lt;p&gt;There's also a real risk of superficial outputs if the underlying thinking isn't solid.&lt;/p&gt;

&lt;p&gt;And we're still relying on models we don't fully control.&lt;/p&gt;

&lt;p&gt;So this isn't about replacing engineering discipline with prompts.&lt;/p&gt;

&lt;p&gt;It's about adding a new layer — one that needs just as much care, if not more.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing thought
&lt;/h2&gt;

&lt;p&gt;NPM packages helped us scale our code, while AI skills could help us scale our thinking.&lt;/p&gt;

&lt;p&gt;This represents a deeper shift than it initially appears.&lt;/p&gt;

&lt;p&gt;We're not just sharing what we build anymore.&lt;br&gt;&lt;br&gt;
We're starting to share how we think.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>designsystem</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Vira Theme: A Deep Dive into the Premium Successor of Material Theme</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Mon, 30 Jun 2025 09:34:27 +0000</pubDate>
      <link>https://dev.to/equinusocio/vira-theme-a-deep-dive-into-the-premium-successor-of-material-theme-1bmb</link>
      <guid>https://dev.to/equinusocio/vira-theme-a-deep-dive-into-the-premium-successor-of-material-theme-1bmb</guid>
      <description>&lt;p&gt;If you've ever loved Material Theme in VS Code, you're going to fall for Vira Theme — it’s the premium evolution, tailored for dark-mode devotees and polished enough to keep developer workflows in mind.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Vira Theme?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Material Theme lineage&lt;/strong&gt; — Vira is the official successor of Material Theme, which powered over 9 million users over 10 years of free service. It retains and improve the beloved aesthetics, while evolving in form and function. Vira Theme, which has been in the works for a whole year, is like the next big thing after Material Theme.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;
      &lt;h4&gt;Teal&lt;/h4&gt;
      &lt;a href="https://vira-themes.github.io/vira-theme-support/assets/previews/teal.webp" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvira-themes.github.io%2Fvira-theme-support%2Fassets%2Fpreviews%2Fteal.webp" width="800" height="400"&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;h4&gt;Ocean&lt;/h4&gt;
      &lt;a href="https://vira-themes.github.io/vira-theme-support/assets/previews/ocean.webp" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvira-themes.github.io%2Fvira-theme-support%2Fassets%2Fpreviews%2Focean.webp" width="800" height="400"&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;h4&gt;Carbon&lt;/h4&gt;
      &lt;a href="https://vira-themes.github.io/vira-theme-support/assets/previews/carbon.webp" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvira-themes.github.io%2Fvira-theme-support%2Fassets%2Fpreviews%2Fcarbon.webp" width="800" height="400"&gt;&lt;/a&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;
      &lt;h4&gt;Palenight&lt;/h4&gt;
      &lt;a href="https://vira-themes.github.io/vira-theme-support/assets/previews/palenight.webp" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvira-themes.github.io%2Fvira-theme-support%2Fassets%2Fpreviews%2Fpalenight.webp" width="800" height="400"&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;h4&gt;Graphene&lt;/h4&gt;
      &lt;a href="https://vira-themes.github.io/vira-theme-support/assets/previews/graphene.webp" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvira-themes.github.io%2Fvira-theme-support%2Fassets%2Fpreviews%2Fgraphene.webp" width="800" height="400"&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;h4&gt;Deepforest&lt;/h4&gt;
      &lt;a href="https://vira-themes.github.io/vira-theme-support/assets/previews/deepforest.webp" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvira-themes.github.io%2Fvira-theme-support%2Fassets%2Fpreviews%2Fdeepforest.webp" width="800" height="400"&gt;&lt;/a&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Exclusively Dark with Distinct Flavor
&lt;/h2&gt;

&lt;p&gt;Vira smartly drops light variants to focus on creating cohesive and polished dark themes, eliminating dilution of effort.&lt;/p&gt;

&lt;p&gt;Choose from &lt;strong&gt;Ocean&lt;/strong&gt;, &lt;strong&gt;Teal&lt;/strong&gt;, &lt;strong&gt;Palenight&lt;/strong&gt;, &lt;strong&gt;Graphene&lt;/strong&gt;, &lt;strong&gt;Deepforest&lt;/strong&gt;, and the star of the show — the new &lt;strong&gt;Carbon&lt;/strong&gt; variant with a near-black background and desaturated syntax coloring.&lt;/p&gt;




&lt;h2&gt;
  
  
  Hand‑crafted Icons &amp;amp; Auto‑Accent Sync
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5son3gjdf1oub6az4ovo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5son3gjdf1oub6az4ovo.png" alt="Vira Icons" width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;over 320 curated file and folder icons&lt;/strong&gt;, each one is uniquely designed and updated to keep your app looking sharp and modern. Plus, automatic accent synchronization links your icon colors with your theme accent, so you can have a unified UI without any hassle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deep Customization
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxn6wmmkm0sg4yawpzqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxn6wmmkm0sg4yawpzqv.png" alt="Vira Theme Settings" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vira lets you customize your experience from the command palette or settings. Here are some options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accent color&lt;/strong&gt;: Choose an accent color or set your.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outlined folder icons&lt;/strong&gt;: Toggle icon styles to match your style.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explorer arrows visibility&lt;/strong&gt;: Choose between a clean or structured look.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editor borders&lt;/strong&gt;: Enable borders to visually distinguish editor sections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern line highlight&lt;/strong&gt;: Choose between a legacy or bold-highlight style.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hide shadows&lt;/strong&gt;: Remove unwanted elevation indicators. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://vira.build/#settings" rel="noopener noreferrer"&gt;Lear more about settings.&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Deps no thanks
&lt;/h2&gt;

&lt;p&gt;Vira Theme is a refreshing change from Material Theme and all the other abandoned clones out there. It’s completely dependency-free, meaning there are no dead dependencies in the final bundle. Plus, you don’t have to download any third-party code. This means no security risks — &lt;a href="https://github.com/microsoft/vsmarketplace/issues/1173#issuecomment-2716936212" rel="noopener noreferrer"&gt;and it’s never been the case&lt;/a&gt;, never trust hate-baiting on internet, they just want to monetize with hate and harassment.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The Material Theme remains functional. However, the VSCode team has implemented policies that make deprecated extensions unavailable. This decision is not within our control. If you locate the VSIX file, you may proceed with its installation and usage, acknowledging the potential consequences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrading to the Vira Theme is not mandatory; no one compels you to migrate from Material Theme. VS Code merely suggests a replacement. If you are dissatisfied with it, you are free to use other extensions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Vira Theme is distinct from the Material Theme. It has undergone a comprehensive overhaul over the past year and a half, incorporating numerous updates, new icons, and features that are not present in the Material Theme.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We offer discount codes to help migrating&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  SUMMER SALES ARE HERE! 🎉
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;After your 7-day free trial&lt;/strong&gt;, you can use the code &lt;code&gt;E0NZIZNW&lt;/code&gt; (valid until &lt;strong&gt;July 30, 2025&lt;/strong&gt;) to get a &lt;strong&gt;35% discount on the 6-activations&lt;/strong&gt; license! No subscription, no fees.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;Try for free&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>design</category>
      <category>vscode</category>
      <category>ux</category>
    </item>
    <item>
      <title>Design with the A+R model</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Fri, 22 Nov 2024 11:30:34 +0000</pubDate>
      <link>https://dev.to/equinusocio/design-adaptive-e-responsive-con-il-modello-a-r-4jon</link>
      <guid>https://dev.to/equinusocio/design-adaptive-e-responsive-con-il-modello-a-r-4jon</guid>
      <description>&lt;h2&gt;
  
  
  What Happens when we combine Adaptive and Responsive design?
&lt;/h2&gt;

&lt;p&gt;Responsive and adaptive design are two approaches used to make websites work on any device, regardless of screen size, ensuring the best user experience. Both aim to optimize screen space and interaction methods, whether users rely on precise pointers or gestures. Before diving into the &lt;strong&gt;A + R&lt;/strong&gt; model, let’s briefly go over both approaches.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;responsive&lt;/strong&gt; approach to design uses CSS and/or JS to adapt layouts and content based on predefined “breakpoints.” On the other hand, the &lt;strong&gt;adaptive&lt;/strong&gt; method provides pre-structured templates tailored to the type of device being used. The former predicts and defines when layouts and content need to change based on orientation, screen size, or content, while the latter delivers targeted experiences based on one key factor: the type of device (and by extension, user) accessing the service. The main difference lies in the structure of the content and HTML. In a responsive approach, the HTML and content structure remain the same (unless JavaScript is used to remove content from the structure) and adapt to different situations. In contrast, adaptive design involves different structures, layouts, and potentially unique experiences.&lt;/p&gt;

&lt;p&gt;Contrary to popular belief, the adaptive approach is widely used in web applications. For instance, creating specific experiences for on-the-go scenarios, where information needs to be easy to access, or for more comfortable desktop settings is common. Twitter, GitHub, and Facebook are prime examples of adaptive design in action.&lt;/p&gt;

&lt;p&gt;Both approaches are valid and widely used. To choose the right one, ask yourself the following questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many components and how much complexity does the project involve?
&lt;/li&gt;
&lt;li&gt;Do users have the same expectations and interactions as desktop users?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Responsive Design Techniques
&lt;/h3&gt;

&lt;p&gt;When building a responsive experience, there are three main techniques for managing layouts and content:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reflow:&lt;/strong&gt; This involves changing the layout structure to use the available space best. Most of the time, the result is content being stacked vertically. While easy, this approach isn’t always the best choice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5r33nwcwjnc388h7pzak.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5r33nwcwjnc388h7pzak.gif" alt=" " width="760" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resize:&lt;/strong&gt; Interface components are designed to be fluid, much like most HTML elements. They fill the available space, and the content adjusts to fit the new dimensions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7fnwj5vhzxu71k1gfim.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7fnwj5vhzxu71k1gfim.gif" alt=" " width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Show/Hide:&lt;/strong&gt; Some interface parts are hidden (but still exist in the structure) or shown, depending on the available space.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshcmtgwujn3vyt4qf887.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshcmtgwujn3vyt4qf887.gif" alt=" " width="760" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adaptive Design Technique
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Restructuring:&lt;/strong&gt; The adaptive approach allows for the development and distribution of different layouts to provide the best experience for specific contexts, such as gesture-only devices or hybrid touch devices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foe64enzncuwc3ow7hj1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foe64enzncuwc3ow7hj1j.png" width="720" height="450"&gt;&lt;/a&gt;Different experiences, different usage&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to the A + R Model
&lt;/h2&gt;

&lt;p&gt;Both approaches have their &lt;strong&gt;pros&lt;/strong&gt; and &lt;strong&gt;cons&lt;/strong&gt;, but what happens when we combine them? The &lt;strong&gt;A + R model&lt;/strong&gt; takes the best of adaptive and responsive design by introducing the concept of major and minor breakpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  A for Adaptive
&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, the adaptive approach allows us to tailor experiences, content, and even features based on the type of device or screen size (usually the more appropriate factor). Major breakpoints are defined to mark the start and end of an experience.&lt;/p&gt;

&lt;p&gt;By setting &lt;strong&gt;960px&lt;/strong&gt; as a major breakpoint (&lt;a href="http://gs.statcounter.com/screen-resolution-stats/tablet/worldwide" rel="noopener noreferrer"&gt;based on global stats&lt;/a&gt;), we can imagine something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdp03ljbgfarh7i1nov9d.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdp03ljbgfarh7i1nov9d.jpeg" width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The left side represents screens smaller than 960px, delivering layouts and content tailored to that type of experience.
&lt;/li&gt;
&lt;li&gt;The right side represents screens larger than 960px, offering an experience designed for that type of navigation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  R for Responsive
&lt;/h3&gt;

&lt;p&gt;The major breakpoint creates two potentially different experiences, within which we can apply responsive design techniques. For each defined experience, we can set minor breakpoints to adapt the layout to the available space. For instance, tablet users might see an experience optimized for touch devices (adaptive), but with layouts that adjust based on device orientation (responsive).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbp3rs6qmi476ibb7cxj2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbp3rs6qmi476ibb7cxj2.jpeg" width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adaptive + Responsive
&lt;/h3&gt;

&lt;p&gt;Combining &lt;strong&gt;Adaptive&lt;/strong&gt; and &lt;strong&gt;Responsive&lt;/strong&gt; approaches results in the &lt;strong&gt;A + R model.&lt;/strong&gt; The adaptive technique defines experiences and functionalities, creating two distinct contexts. Meanwhile, the responsive technique manages interface components, layouts, and behaviors within each context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fta7t75mtgz4ycedkzkp8.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fta7t75mtgz4ycedkzkp8.jpeg" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Choose This Model
&lt;/h3&gt;

&lt;p&gt;This approach requires designers and developers to fully understand the experiences they want to deliver. It’s typically used for large applications that need to be optimized for mobile devices, requiring various functionalities and layouts. While it offers flexibility and customization, it also introduces complexity, as you might end up managing two separate projects or environments, which is not recommended.&lt;/p&gt;

&lt;p&gt;If the team decides to follow the A + R model, they can focus on delivering curated, targeted experiences based on user type—something a purely responsive approach cannot achieve, as it’s always a compromise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who Uses the A + R Model?
&lt;/h3&gt;

&lt;p&gt;Many online services we use daily follow this approach. Twitter, Facebook, and GitHub, for example, provide dedicated mobile apps rather than simply stacking and hiding parts of their desktop content. If you access these services on your mobile device, you’ll notice tailored experiences designed to meet the expectations of mobile users compared to desktop users.&lt;/p&gt;

</description>
      <category>ux</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Introducing Native Elements</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Thu, 18 Jun 2020 15:27:08 +0000</pubDate>
      <link>https://dev.to/equinusocio/introducing-native-elements-4j5i</link>
      <guid>https://dev.to/equinusocio/introducing-native-elements-4j5i</guid>
      <description>&lt;p&gt;HTML elements with CSS superpowers. 🔥&lt;/p&gt;

&lt;p&gt;Native Elements (NE) is not a CSS framework, no bundlers required or tons of configurations to set. You can consider it as a customizable plug-n-play library for your site which helps you easily style all the available HTML elements using CSS custom properties, classes, attributes, or whatever you want in less than &lt;code&gt;6 kB&lt;/code&gt;. You can also build your class-based CSS framework on top of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;This library is built using modern CSS feature and best practices, the compiled version supports only the latest two Chrome, Safari, Firefox, and Edge versions and this is possible thanks to &lt;a href="https://github.com/browserslist/browserslist" rel="noopener noreferrer"&gt;Browserslist&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Modern
&lt;/h3&gt;

&lt;p&gt;Built on top of PostCSS takes advantage of exciting new CSS features, like custom and logical properties. If you use it from source, you can define custom selectors and mixins to make styling even easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Framework agnostic
&lt;/h3&gt;

&lt;p&gt;In the age of Flexbox, CSS grid, and other exciting layout features, there is less and less need for a bloated CSS framework. What you do need is a simple foundation on top of which to build your styles.&lt;/p&gt;

&lt;p&gt;If you're using the compiled version, just drop it inside your application main style. It's just CSS, so it works with &lt;a href="https://reactjs.org" rel="noopener noreferrer"&gt;React&lt;/a&gt;, &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt;, &lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt; and &lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;Svelte.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy theming
&lt;/h3&gt;

&lt;p&gt;With our &lt;a href="https://app.native-elements.dev" rel="noopener noreferrer"&gt;theme builder&lt;/a&gt; tool you can create, tweak, and export your theme easily. In the future, we'll share new premade themes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Making a theme
&lt;/h2&gt;

&lt;p&gt;Thanks to the &lt;a href="https://app.native-elements.dev/" rel="noopener noreferrer"&gt;Theme Builder&lt;/a&gt; app you can create your color palette, visually change and preview all the available custom properties, and download a ready-to-use theme that you can include in your project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.native-elements.dev/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnative-elements.dev%2Fimg%2Ftb.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using themes
&lt;/h3&gt;

&lt;p&gt;Once you have your set of custom properties, there few ways to use it. You can put the custom properties inside the global &lt;code&gt;:root&lt;/code&gt; of your css, or scope it inside a custom selectors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Global themes
&lt;/h3&gt;

&lt;p&gt;When you put your theme inside the &lt;code&gt;:root&lt;/code&gt; selector it will be applied to all the elements of your page. This is useful when you have one theme active at time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-body-font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-root-font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-body-font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.125rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-selection-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-selection-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;233&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;64%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;72%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-outline-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-outline-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-basic-line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-headings-scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-quote-font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-cite-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-cite-font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-cite-start-sign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'—'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-links-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-links-active-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;233&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;64%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;52%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-del-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;337&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;74%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;31%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-del-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;94%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scoped themes
&lt;/h3&gt;

&lt;p&gt;The CSS's cascade is very useful to make scoped themes, it affects custom properties like other properties.&lt;/p&gt;

&lt;p&gt;If you want to divide your theme into multiple pieces, you can wrap the custom properties inside separate selectors. Every element inside that selector will inherit the theme, while elements outside it will use their default style.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"dark"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-body-font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-root-font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-body-font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.125rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.NeumorphicTheme&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--ne-body-font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-root-font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--ne-body-font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.125rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When to use it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You're working on projects for &lt;strong&gt;modern and secure web browsers&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You're not going to mix other CSS frameworks&lt;/li&gt;
&lt;li&gt;You want to save time sacrificing a bit of flexibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  More on &lt;a href="https://native-elements.dev" rel="noopener noreferrer"&gt;native-elements.dev&lt;/a&gt;
&lt;/h2&gt;

</description>
      <category>css</category>
      <category>html</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Making dark theme switcher with PostCSS.</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Tue, 12 May 2020 08:17:24 +0000</pubDate>
      <link>https://dev.to/equinusocio/making-dark-theme-switcher-with-postcss-187i</link>
      <guid>https://dev.to/equinusocio/making-dark-theme-switcher-with-postcss-187i</guid>
      <description>&lt;p&gt;You have noticed that there is a new design trend that is floating around web design since 2019, the dark mode. Facebook, Apple, and Google both introduced the dark version of their software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a dark theme
&lt;/h2&gt;

&lt;p&gt;Most of you probably think this is just a trend that will disappear after some years, well, let me say that this is not like many other trends, dark UI provide different advantages and they are not something just related to the "designer mood". Let's see why a dark mode on your applications and websites are something useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better for batteries
&lt;/h3&gt;

&lt;p&gt;Pixels on a screen consume more energy to display light colors rather than dark ones. Consequently, devices' batteries can save energy and improve their daily duration while using dark UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better for dark environments
&lt;/h3&gt;

&lt;p&gt;Most of us use their smartphone and laptops while at home. Such environments are typically not so bright. The dark mode can help the use of the application while indoor, without causing visual disturbances.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better for people
&lt;/h3&gt;

&lt;p&gt;Some people with — or without — visual diseases, like epilepsy, can have unfortunate events by being flashed by bright applications. Having a dark mode means being more accessible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing styles
&lt;/h2&gt;

&lt;p&gt;A very simple theme switcher should offer at least 3 options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dark theme&lt;/li&gt;
&lt;li&gt;Light theme&lt;/li&gt;
&lt;li&gt;Automatic theme (should be on by default)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wait, what's the automatic theme? Well, modern operating systems allow users to change the global visual appearance by setting os-wide options that enable the dark or light mode. The automatic option make sure to respect the OS preference if the user has not specified any theme.&lt;/p&gt;

&lt;p&gt;To make this even more simple, we'll use PostCSS and a simple but useful plugin called &lt;a href="https://github.com/postcss/postcss-dark-theme-class" rel="noopener noreferrer"&gt;&lt;code&gt;postcss-dark-theme-class&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add postcss-dark-theme-class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This plugin will do 70% of the work, once installed, add it to your PostCSS config and configure the selectors you want to use to activate the correct theme, which will be used by the plugin to generate the correct CSS:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="cm"&gt;/* ...other plugins */&lt;/span&gt;

    &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postcss-dark-theme-class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
      &lt;span class="na"&gt;darkSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-theme="dark"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lightSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-theme="light"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once the plugin is up and running, we can start defining our dark and light themes using a CSS specific media query &lt;code&gt;prefers-color-scheme&lt;/code&gt;. This special media query will handle the automatic part of our themes by applying the correct theme based on the user's OS preferences:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;226deg&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;226deg&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the user is using a dark version of his OS, the set inside the media query will apply, overwriting others, otherwhise the set of properties outside the media query is used. Since it's pure CSS, this behaviour is on by default.&lt;/p&gt;

&lt;p&gt;Browsers will now adapt the color scheme automatically based on the users' OS preferences. Nice done! 🚀 Now it's time to make the theme switcher allow users to specify what theme to use, overriding the OS preference.&lt;/p&gt;
&lt;h2&gt;
  
  
  Making the theme switcher
&lt;/h2&gt;

&lt;p&gt;As we said, our switcher should have three options, we can use a simple select element, or build a set of buttons:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;data-set-theme=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Auto&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;data-set-theme=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Dark&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;data-set-theme=&lt;/span&gt;&lt;span class="s"&gt;"light"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Light&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We'll build the switcher using vanilla JS, but you can do it with any framework you want, the concept is the same: we have to add the selectors we defined inside the PostCSS plugin to the &lt;code&gt;root&lt;/code&gt; element, based on the clicked button.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;themeButtons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-set-theme]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;themeButtons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Each time we click on a theme button, the value set as &lt;code&gt;data-set-theme&lt;/code&gt; is applied as value of the &lt;code&gt;data-theme&lt;/code&gt; attribute on the document root element, we also change the &lt;code&gt;[aria-current]&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;Check it live:&lt;/p&gt;


&lt;div class="glitch-embed-wrap"&gt;
  &lt;iframe src="https://glitch.com/embed/#!/embed/theme-switcher-with-postcss?path=index.html" alt="theme-switcher-with-postcss on glitch"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Where is the magic?
&lt;/h2&gt;

&lt;p&gt;The magic is made by &lt;code&gt;postcss-dark-theme-class&lt;/code&gt; — which will add our &lt;code&gt;[data-theme]&lt;/code&gt; custom attribute to the &lt;code&gt;:root&lt;/code&gt; selectors we wrote — during the CSS transpilation. Here what it generates from our code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Our automatic and user specified light theme */&lt;/span&gt;
&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;226deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Our automatic dark theme */&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;:root:not&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="nt"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"light"&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;226deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Our dark theme specified by the user */&lt;/span&gt;
&lt;span class="nd"&gt;:root&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"dark"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;226deg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bonus tip
&lt;/h2&gt;

&lt;p&gt;You may notice that the &lt;code&gt;--accent-color&lt;/code&gt; custom property defined inside themes doesn't change. If you have colors that will not change based on the theme, you can remove them from the &lt;code&gt;prefers-color-scheme&lt;/code&gt; at-rule.&lt;/p&gt;

&lt;p&gt;In this way, they will not be duplicated and the one defined outside the media query will always apply.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;226deg&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--global-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--global-foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>css</category>
      <category>a11y</category>
      <category>html</category>
      <category>customproperties</category>
    </item>
    <item>
      <title>Making Web Components for Different Contexts</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Tue, 07 May 2019 14:08:48 +0000</pubDate>
      <link>https://dev.to/equinusocio/making-web-components-for-different-contexts-25ed</link>
      <guid>https://dev.to/equinusocio/making-web-components-for-different-contexts-25ed</guid>
      <description>&lt;p&gt;This article isn’t about how to build web components. Caleb Williams already wrote a &lt;a href="https://css-tricks.com/an-introduction-to-web-components/" rel="noopener noreferrer"&gt;comprehensive guide&lt;/a&gt; about that recently. Let’s talk about how to work with them, what to consider when making them, and how to embrace them in your projects.&lt;/p&gt;

&lt;p&gt;If you are new to web components, Caleb’s guide is a great read, but here are more resources that will get you up to speed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://equinsuocha.io/blog/web-components-the-right-way" rel="noopener noreferrer"&gt;Web Components — the "right" way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/web/fundamentals/web-components/shadowdom" rel="noopener noreferrer"&gt;Shadow DOM v1: Self-Contained Web Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" rel="noopener noreferrer"&gt;Web Components on MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mateusortiz/webcomponents-the-right-way" rel="noopener noreferrer"&gt;Awesome Web Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://open-wc.org/" rel="noopener noreferrer"&gt;Open Web Component Recommendations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since web components are now &lt;a href="https://caniuse.com/#search=shadow" rel="noopener noreferrer"&gt;widely supported&lt;/a&gt; (thanks to the hard work of many people behind the scenes) — and considering the &lt;a href="https://css-tricks.com/edge-goes-chromium-what-does-it-mean-for-front-end-developers/" rel="noopener noreferrer"&gt;imminent switch&lt;/a&gt; that Edge will make to the chromium platform — people are now thinking about web components as "native" and a platform-compliant way to build reusable UI components to keep consistency across design systems and web projects, while using the power of the Shadow DOM to encapsulate style and logics inside the component itself.&lt;/p&gt;

&lt;p&gt;Well, this can be true and false at the same time. But first, let’s get acquainted with the &lt;strong&gt;Abstraction Layers Triangle&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Abstraction Layers Triangle
&lt;/h2&gt;

&lt;p&gt;Technically, we should consider web components as an extension of our favorite markup language, HTML (yep!). The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" rel="noopener noreferrer"&gt;Web Components API&lt;/a&gt; allows us to create custom HTML elements (e.g. &lt;code&gt;&amp;lt;foo-bar&amp;gt;&lt;/code&gt;) that don’t exist in HTML.&lt;/p&gt;

&lt;p&gt;We are told web components are basically new HTML elements, so we should consider them as part of the HTML specifications and, consequently, we should follow its paradigms, core concepts, and utilisation. If we assume all of these points, we will figure out that our components will live among the lowest levels of the web platform stack, alongside HTML, CSS, and JavaScript.&lt;/p&gt;

&lt;p&gt;Frameworks and libraries like React, Vue, Angular, SvelteJS work on their abstraction level, right above other tools that live in a sort of "middle earth," like StencilJs, Hybrids and Lit. Under these layers of abstraction, we can find our basic web technologies… and vanilla web components. We can represent this concept with an &lt;strong&gt;ALT&lt;/strong&gt; (&lt;strong&gt;A&lt;/strong&gt;bstraction &lt;strong&gt;L&lt;/strong&gt;ayers &lt;strong&gt;T&lt;/strong&gt;riangle) diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcss-tricks.com%2Fwp-content%2Fuploads%2F2019%2F04%2Fs_5B36036EA3CCD2962258CADABD44B400D52827409ACCBE3D636781BACC2B8EDC_1554105948178_al.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcss-tricks.com%2Fwp-content%2Fuploads%2F2019%2F04%2Fs_5B36036EA3CCD2962258CADABD44B400D52827409ACCBE3D636781BACC2B8EDC_1554105948178_al.svg" alt="ALT" width="739" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why is this important? Well, it helps us visualise the various layers that exist on top of native components and understand the context they are used so that they can be built for an intended context. What's context? That's where we're headed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same technology, different contexts
&lt;/h2&gt;

&lt;p&gt;The Shadow DOM is a key factor in the Web Components API. It allows us to bundle JavaScript and CSS inside a custom element to both prevent external interferences and style manipulations, unless we expressly allow it. There are indeed some approaches that developers can follow to allow external CSS to leak into the shadow root and into a component, including custom properties and the &lt;code&gt;::part&lt;/code&gt; and &lt;code&gt;::theme&lt;/code&gt; pseudo-elements, which is something &lt;a href="https://twitter.com/notwaldorf" rel="noopener noreferrer"&gt;Monica Dinculescu&lt;/a&gt;) has &lt;a href="https://meowni.ca/posts/part-theme-explainer/" rel="noopener noreferrer"&gt;covered so well&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is also another thing to consider: the context we are working with. After three years of building web components personally, I can identify two contexts: the &lt;strong&gt;private context&lt;/strong&gt; (like a design system) and the &lt;strong&gt;standard context&lt;/strong&gt; (like plain HTML, CSS, and JavaScript without custom styles).&lt;/p&gt;

&lt;p&gt;Before designing components, we need to know how they will be used, so determining the type of context is a key to all of this. The most easy way is targeting only one context, but with a small CSS trick. we can build our components for both of them.&lt;/p&gt;

&lt;p&gt;Let’s look at the differences between the two contexts before we get into that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Private context
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;private context&lt;/strong&gt; is a closed ecosystem that provides components with their own style that must be used as-is. So, if we are building a component library that comes from specific styling guidelines or a design system, each component will reflect custom styles so there’s no need to code them up each time they’re needed.&lt;/p&gt;

&lt;p&gt;That can be true also with JavaScript logic. For example, we can attach a closed shadow root that prevent others to accidentally pierce the shadow boundary with a &lt;code&gt;querySelector&lt;/code&gt;. As a a result, we can simply pick and use all any component, avoiding issues like style inconsistencies and CSS collisions. As the author, you can also get to define a set of CSS custom properties (or &lt;code&gt;::parts&lt;/code&gt;) that can be used to style a component for a specific use case, but this is not the focus point of a design system.&lt;/p&gt;

&lt;p&gt;Here’s an example of a web component component in a private context. It has all of the styles and logic contained inside its &lt;code&gt;shadow-root&lt;/code&gt; and and can simply be dropped into any page.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/equinusocio/embed/WWbQdP?height=600&amp;amp;default-tab=html,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This example and the one to follow are for demonstration purposes and not intended for production use because they do not make considerations for key situations, like accessibility and other optimisations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Components in a private context can be rarely used outside of that context. For example, if we try to take an element from a design system (which has its own enforced styles), we’re unable to simply add it to a project and expect to customise it. You know how Bootstrap can be themed and customised to your liking? This is pretty much the opposite of that. These components are made to live inside their context and their context only.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standard context
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;standard&lt;/strong&gt; context may be the most complex type of component, not only because the environment can range anywhere from a full-fledged framework (like Vue and React) to plain vanilla HTML, but also because everyone should be able to use that component like any other element.&lt;/p&gt;

&lt;p&gt;For example, when adding a component publicly, say to npm, those who use it will expect to be able to customise it, at least to some degree.&lt;/p&gt;

&lt;p&gt;Do you know of any HTML element that comes with its own presentational style? The answer should be no because, well, elements must be explicitly styled with CSS. This is also true for web components made in a standard context. A single web component should be customisable by adding classes an attributes, or other methods.&lt;/p&gt;

&lt;p&gt;Here’s the same &lt;code&gt;&amp;lt;todo-list&amp;gt;&lt;/code&gt; element that we saw in the closed context example, but designed for a standard context. It works as-is, without any presentational styles inside its shadow root. In fact, it only contains the required logic and baseline CSS to make sure it functions. Otherwise, it’s completely customisable like any standard HTML element, like a div.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/equinusocio/embed/vMOqBO?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Both of the examples we’ve looked at for each context are made with the same component. The difference is that the component in a standard context an be customised and selected with external CSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web components and composition
&lt;/h2&gt;

&lt;p&gt;OK, so working with web components is really the same as working with plain HTML, though as we’ve seen, it’s important to follow the paradigms and principles of the given content. Well, thing we need to be mindful of is the web component composition.&lt;/p&gt;

&lt;p&gt;As explained by &lt;a href="https://developers.google.com/web/fundamentals/web-components/shadowdom#composition_slot" rel="noopener noreferrer"&gt;Google Web Fundamentals&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Composition is one of the least understood features of shadow DOM, but it's arguably the most important.&lt;/p&gt;

&lt;p&gt;In our world of web development, composition is how we construct apps, declaratively out of HTML. Different building blocks (&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s, &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;s, &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;s, &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;s) come together to form apps. Some of these tags even work with each other. Composition is why native elements like &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; are so flexible. Each of those tags accepts certain HTML as children and does something special with them. For example, &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; knows how to render &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;optgroup&amp;gt;&lt;/code&gt; into dropdown and multi-select widgets. The &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element renders &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt; as an expandable arrow. Even &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; knows how to deal with certain children: &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; elements don't get rendered, but they do affect the video's behavior. What magic!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Composition is what we normally do when we work with HTML. Since web components are merely HTML elements with a DOM reference — and not logical containers — we should rely on composition to build our components and any sub-components. If you think about the &lt;code&gt;ul&lt;/code&gt; and and &lt;code&gt;select&lt;/code&gt; you will notice that you declaratively compose these elements to get the final output and you have specific attributes to be used with the main component (e.g. &lt;code&gt;[readonly]&lt;/code&gt;) or the sub-component (e.g. &lt;code&gt;[selected]&lt;/code&gt;). This is true also for web components, and if you are building a custom list, consider to build the main component (&lt;code&gt;&amp;lt;custom-list&amp;gt;&lt;/code&gt;) and the child one (&lt;code&gt;&amp;lt;custom-li&amp;gt;&lt;/code&gt;). &lt;a href="https://css-tricks.com/extracting-text-from-content-using-html-slot-html-template-and-shadow-dom/" rel="noopener noreferrer"&gt;Using the &lt;code&gt;[slot]&lt;/code&gt; element&lt;/a&gt;, you can define where children elements will be placed and also placeholder content that will be shown when no children are passed through.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web components and accessibility
&lt;/h2&gt;

&lt;p&gt;Another thing to consider is that "small" topic we call accessibility. Since we are creating completely new HTML elements, we need to consider the accessibility of our elements in order to provide a basic semantic role, any keyboard navigation as well as the user’s operating system preferences, like the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion" rel="noopener noreferrer"&gt;reduce motion&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/-ms-high-contrast" rel="noopener noreferrer"&gt;high contrast&lt;/a&gt; settings.&lt;/p&gt;

&lt;p&gt;I strongly suggest the following resources as reference for building accessible and inclusive components, how to define semantic markup, and how to implement a basic keyboard navigation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://inclusive-components.design/" rel="noopener noreferrer"&gt;Inclusive Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/accessible" rel="noopener noreferrer"&gt;Accessible to All on web.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/TR/wai-aria-practices-1.2/" rel="noopener noreferrer"&gt;WAI-ARIA Authoring Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webaim.org/standards/wcag/checklist" rel="noopener noreferrer"&gt;WebAIM WCAG Checklist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Web components are an emerging technology in web development and, as such, there really aren’t any clearly defined best practices to guide us as far as building them for their intended or maximized use. When you find yourself working with them, perhaps the single thing you can take away from this post is to consider whether they are intended for a closed context or a standard context, then ask yourself &lt;strong&gt;WHI&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;W&lt;/strong&gt;ho will use this component?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;H&lt;/strong&gt;ow much flexibility should that person have to customize it?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I&lt;/strong&gt;s this component for everyone or for a specific audience?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webcomponents</category>
      <category>html</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Adaptive + Responsive model</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Tue, 12 Feb 2019 15:26:33 +0000</pubDate>
      <link>https://dev.to/equinusocio/the-adaptive--responsive-model-45mn</link>
      <guid>https://dev.to/equinusocio/the-adaptive--responsive-model-45mn</guid>
      <description>&lt;p&gt;You can call it &lt;strong&gt;Adansive&lt;/strong&gt; or &lt;strong&gt;Resaptive&lt;/strong&gt;..&lt;/p&gt;

&lt;p&gt;Responsive and Adaptive design are two design methodologies with the goal of making a product accessible on any device or screen size, providing the best experience to all users. Both of them try to make the most of the available screen space and the user interaction mode. Before talking about the &lt;strong&gt;A+R&lt;/strong&gt; model we need to break down both methodologies approaches &lt;/p&gt;

&lt;p&gt;While &lt;strong&gt;responsive&lt;/strong&gt; design makes use of CSS and/or JS to adapt layouts and contents based on predefined breakpoints, the &lt;strong&gt;adaptive&lt;/strong&gt; approach provides pre-structured templates that will be served based on the user agent and the device type. The main difference between them is the DOM structure, when approaching with a responsive mindset we have the same HTML code for all situations (unless you use JS to remove some DOM nodes), while in adaptive we have a different code structure and potentially different experiences.&lt;/p&gt;

&lt;p&gt;Both design mindsets are valid, just ask yourself how many components and complexities you have in your project and if one experience can fit all of your users. Developing web applications the responsive design is frequently used, such as building specific experiences through an adaptive development, like Twitter and Facebook mobile do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsive Design Techniques
&lt;/h2&gt;

&lt;p&gt;While building a responsive experience we have three approaches to handle our layouts and content:&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Reflow&lt;/strong&gt;: We can change the layout structure to better fit the viewport area. Most of time this results in content being stacked (that's not always good).&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/gz0sygvqczyz/65UW1zPCu13qSmdatPZlhS/601e3a5f2bdc5ba347f3d08c45317235/5c61879965585.gif" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/gz0sygvqczyz/65UW1zPCu13qSmdatPZlhS/601e3a5f2bdc5ba347f3d08c45317235/5c61879965585.gif" alt="5c61879965585"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Resize:&lt;/strong&gt; Some of the UI components are fluid like most of html elements. They fill the available space and reflow if necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/gz0sygvqczyz/3958w8EeBmawW9fxqZXfUC/b008d45133ac7f03b1eb8e927f4f05e4/5c618ef61271a.gif" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/gz0sygvqczyz/3958w8EeBmawW9fxqZXfUC/b008d45133ac7f03b1eb8e927f4f05e4/5c618ef61271a.gif" alt="5c618ef61271a"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Show/Hide:&lt;/strong&gt; Some UI parts are hidden from the viewport (but they still exist) or showed up to fill the space.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/gz0sygvqczyz/7ECGrNclFOLOYPO12yNlOa/6cd743d8e07ad6238462fdef2423d5f0/5c629b5ec96d8.gif" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/gz0sygvqczyz/7ECGrNclFOLOYPO12yNlOa/6cd743d8e07ad6238462fdef2423d5f0/5c629b5ec96d8.gif" alt="5c629b5ec96d8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Restructuring:&lt;/strong&gt; With this approach we can develop and deliver different layouts to provide the best experience for a specific environment like a touch-only mobile device, or hybrid-touch devices.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/gz0sygvqczyz/3Ykv98R1ejIg0AFGzmjfsB/1ecefef84320cf91b81486556dbce506/5c619176816f9.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/gz0sygvqczyz/3Ykv98R1ejIg0AFGzmjfsB/1ecefef84320cf91b81486556dbce506/5c619176816f9.png" alt="5c619176816f9"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing the A+R model
&lt;/h2&gt;

&lt;p&gt;Both approaches have pro and cons, but what do we get if we want to use both of them? The &lt;strong&gt;A+R&lt;/strong&gt; model combines both the responsive and adaptive approaches based on a single major breakpoint. &lt;/p&gt;

&lt;h3&gt;
  
  
   A stands for Adaptive
&lt;/h3&gt;

&lt;p&gt;As mentioned above, the adaptive approach allows us to differentiate the user experience, contents and even functionalities based on the user device. Considering a &lt;strong&gt;960px&lt;/strong&gt; as major adaptive breakpoint (&lt;a href="http://gs.statcounter.com/screen-resolution-stats/tablet/worldwide" rel="noopener noreferrer"&gt;defined based on global stats&lt;/a&gt;), we have something similar: &lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/gz0sygvqczyz/5qvXnLZ4VK7rAko5IWQ0VP/e2b53e5dd86381b7eb05b8c3afb03e0a/5c61a09419d77.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/gz0sygvqczyz/5qvXnLZ4VK7rAko5IWQ0VP/e2b53e5dd86381b7eb05b8c3afb03e0a/5c61a09419d77.png" alt="5c61a09419d77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The viewport area on the left represent all the screens under a 960px  with a specific layout/content&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The viewport area on the right represent all the screens with a 960px or greater with another layout.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  R stands for Responsive
&lt;/h3&gt;

&lt;p&gt;The major breakpoint we have defined create two exprience contexts that may be different from each other, in which we can apply the responsive techniques. Inside each experience we can define minor breakpoints to adapt the layout based on the available space. For example, users which use a tablet will may see a touch-optimised experience (adaptive), but we can still adapt the layout based on the device orientation (responsive).&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/gz0sygvqczyz/41vr70gcIuTyC12VMlrrSC/1594a240a1a6bf171ce87b19608c38df/5c62a707337cd.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/gz0sygvqczyz/41vr70gcIuTyC12VMlrrSC/1594a240a1a6bf171ce87b19608c38df/5c62a707337cd.png" alt="5c62a707337cd"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adaptive + Responsive
&lt;/h2&gt;

&lt;p&gt;Combining Adaptive and Responsive approaches we get the &lt;strong&gt;A + R model&lt;/strong&gt;. With the adaptive technique we will work on experiences and functionalities, making two different contexts. Withe the responsive one we handle the UI components and layouts which stand inside the contexts.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/gz0sygvqczyz/4IfXMr6udDCdhGge4E0JTz/6daae93d3abbbe04b6184e76f84156d6/5c62a992ae5af.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/gz0sygvqczyz/4IfXMr6udDCdhGge4E0JTz/6daae93d3abbbe04b6184e76f84156d6/5c62a992ae5af.png" alt="5c62a992ae5af"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When to choose the A + R model
&lt;/h2&gt;

&lt;p&gt;This design approach require designers to really understand the experiences they want to provide in order to define what model to follow. This model fit well for large applications that must be accessible from small mobile devices with less functionalities or with a completely different structure. As you can see you will get a lot of flexibility, but also complexity because you may have to handle different codebases and environments (not mandatory).&lt;/p&gt;

&lt;p&gt;With the A+R model mindset, designers and developers (but also product owners) can be focused to improve all the experiences the product can offers, instead to provide a "good" experience only on one environment.&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://equinsuocha.io/blog/the-adaptive-responsive-model" rel="noopener noreferrer"&gt;equinsuocha.io&lt;/a&gt;. All the images are made by me and the Contactlab UX team.&lt;/p&gt;

</description>
      <category>css</category>
      <category>html</category>
      <category>ux</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Fieldset, this stranger.</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Fri, 08 Feb 2019 18:21:32 +0000</pubDate>
      <link>https://dev.to/equinusocio/fieldset-this-stranger-55pf</link>
      <guid>https://dev.to/equinusocio/fieldset-this-stranger-55pf</guid>
      <description>&lt;p&gt;Field..wat?? Yep, it still exist but no one seems to remember it. This guy is a &lt;a href="https://html.spec.whatwg.org/multipage/form-elements.html#the-fieldset-element" rel="noopener noreferrer"&gt;living standard form element&lt;/a&gt; that is made to represent a set of elements inside a form or grouping related elements like labels, inputs, meters, paragraphs etc... and it doesn't end here, it can be nested and can contains any kind of elements.&lt;/p&gt;

&lt;p&gt;Are you still interested? So i will tell you two more things, it can also accept three really useful html attributes that will help you making your beautiful forms aaaand....it's not made to wrap only radio buttons! 😱&lt;/p&gt;

&lt;h2&gt;
  
  
  The specification
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;The fieldset element represents a set of form controls (&lt;em&gt;or other content&lt;/em&gt;) grouped together, optionally with a caption. The caption is given by the first &lt;a href="https://html.spec.whatwg.org/multipage/form-elements.html#the-legend-element" rel="noopener noreferrer"&gt;legend&lt;/a&gt; element that is a child of the fieldset element, &lt;em&gt;if any&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;— &lt;a href="https://html.spec.whatwg.org/multipage/form-elements.html#the-fieldset-element" rel="noopener noreferrer"&gt;WHATWG&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's pretty clear what you should do with this element and when using it. As mentioned above it can also accept three attributes: &lt;code&gt;form&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;disabled&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FORM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This attribute allows you to associate a group of inputs to a specific form element that is not its ancestor. This means that you can fix the lack of the possibility to nest forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NAME&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The name of the group to use in the &lt;a href="https://html.spec.whatwg.org/multipage/forms.html#dom-form-elements" rel="noopener noreferrer"&gt;form.elements&lt;/a&gt; API&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DISABLED&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the same global attribute you use on buttons and inputs. It disable at once all the child elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  A use case
&lt;/h2&gt;

&lt;p&gt;Let's take a real example making a form with disabled sections controlled by checkboxes. In this form we will use label, inputs and the output element and we can build it by making the most of fieldset attributes and a bit of javascript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"calculatorForm"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;fieldset&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"enableCalc"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"enableCalc"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Enable calc&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;fieldset&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"calculator"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Default formula --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;fieldset&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"defaultcalc"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"default"&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"default"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Use default calculation&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Custom formula --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;fieldset&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"customcalc"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Use custom calculation&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"c"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"d"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=
      &lt;span class="nt"&gt;&amp;lt;output&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"x"&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"c d"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;100&lt;span class="nt"&gt;&amp;lt;/output&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example we have a form with a fieldset named "calculator" which is disabled by default. When clicking the &lt;code&gt;enableCalc&lt;/code&gt;checkbox the calculator area will be enabled. Here the live demo.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://jsfiddle.net/equinusocio/2fm4Lksc/embedded/result,html//dark" width="100%" height="600"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Apart the javascript integration, the point here is &lt;code&gt;fieldset&lt;/code&gt; element. It's live, it's standard and it's useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Bad" examples from...
&lt;/h2&gt;

&lt;p&gt;The following examples are neither wrong or correct, but why not break this loop of "not-so-good practices" and start improving our code the same way we iper-improve our javascript code?&lt;/p&gt;

&lt;h3&gt;
  
  
  Twitter Bootstrap
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"formGroupExampleInput"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Example label&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"formGroupExampleInput"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ZURB Foundation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input-group"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input-group-field"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"url"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input-group-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Material Design Components
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mdc-form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mdc-checkbox"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"my-checkbox"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mdc-checkbox__native-control"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mdc-checkbox__background"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      ...
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"my-checkbox"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;This is my checkbox&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tailwind CSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mb-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"block text-grey-darker"&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Username&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Username"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see many popular frameworks don't use fieldset (bootstrap mention it but nothing more) as form elements container and that's really weird because HTML have all the tools we need to build our webpages and applications. We should not recreate what the platform already provide, instead we just need to learn it and eventually how to extend it, for example with &lt;a href="https://equinsuocha.io/blog/web-components-the-right-way" rel="noopener noreferrer"&gt;web components&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
      <category>html</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
    <item>
      <title>ckd.css for your ticks</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Fri, 21 Dec 2018 16:30:41 +0000</pubDate>
      <link>https://dev.to/equinusocio/ckdcss-for-your-ticks-5033</link>
      <guid>https://dev.to/equinusocio/ckdcss-for-your-ticks-5033</guid>
      <description>&lt;p&gt;&lt;a href="https://ckdcss.now.sh"&gt;ckd.css&lt;/a&gt; v2 has been released and it will bring beautiful and small micro interactions to your checkboxes and radios. You can use it even on your custom imputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are micro interactions important?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s likely that you started your day with a micro-interaction. By turning off the alarm on your mobile phone, you engaged with a user interface in a single moment.&lt;/p&gt;

&lt;p&gt;You will continue to engage throughout the day in these moments with your digital devices. Each one is a micro-interaction. Each one is probably so small you don’t think about it. And each one works because of that simple fact.&lt;/p&gt;

&lt;p&gt;As a designer, recognizing the invisibility of micro-interactions is just as important as designing them. You have to create something that feels human and accomplishes a task, making the life of a user easier. You also have to focus on a design that can work in a variety of environments and does not need any instruction or explanation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;— &lt;a href="https://thenextweb.com/dd/2015/08/17/why-micro-interactions-are-the-secret-to-great-design/"&gt;The Next Web&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/equinusocio"&gt;
        equinusocio
      &lt;/a&gt; / &lt;a href="https://github.com/equinusocio/ckdcss"&gt;
        ckdcss
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A tiny set of micro interactions for your checkboxes.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/887005efb2eb1c9428d3e6b18c713b02b13480e9/68747470733a2f2f692e6962622e636f2f4c64365134704d2f636b642e706e67"&gt;&lt;img width="600px" src="https://camo.githubusercontent.com/887005efb2eb1c9428d3e6b18c713b02b13480e9/68747470733a2f2f692e6962622e636f2f4c64365134704d2f636b642e706e67"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;      &lt;a href="https://npmcharts.com/compare/ckd-css?minimal=true" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/c9f4901f7cba1227cb758431fc007724bc1fb9fb/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f636b642d6373732e7376673f7374796c653d666f722d7468652d626164676526636f6c6f72413d43443441344126636f6c6f72423d423033373337" alt="Downloads"&gt;&lt;/a&gt;
 
 
&lt;a href="https://bundlephobia.com/result?p=ckd-css" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/77161b5f52abcaf37aefb14a268cd7882652bef3/68747470733a2f2f696d672e736869656c64732e696f2f62756e646c6570686f6269612f6d696e7a69702f636b642d6373732e7376673f7374796c653d666f722d7468652d626164676526636f6c6f72413d30303030303026636f6c6f72423d314238344646266c6162656c3d677a69706564" alt="Size"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;br&gt;

&lt;br&gt;
&lt;h2&gt;
Why?&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s likely that you started your day with a micro-interaction. By turning off the alarm on your mobile phone, you engaged with a user interface in a single moment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;You will continue to engage throughout the day in these moments with your digital devices. Each one is a micro-interaction. Each one is probably so small you don’t think about it. And each one works because of that simple fact.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;As a designer, recognizing the invisibility of micro-interactions is just as important as designing them. You have to create something that feels human and accomplishes a task, making the life of a user easier. You also have to focus on a design that can work in a variety of environments and does not need any instruction or explanation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Source: &lt;a href="http://thenextweb.com/dd/2015/08/17/why-micro-interactions-are-the-secret-to-great-design/" rel="nofollow"&gt;The Next Web&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;h3&gt;
As dependency&lt;/h3&gt;
&lt;p&gt;You can install &lt;strong&gt;ckd-css&lt;/strong&gt; as node dependency by using &lt;a href="https://www.npmjs.com/package/ckd-css" rel="nofollow"&gt;Npm&lt;/a&gt; or &lt;a href="https://yarnpkg.com/" rel="nofollow"&gt;Yarn&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;
&lt;pre&gt;npm install&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/equinusocio/ckdcss"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>css</category>
      <category>ux</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How to load web fonts in 2018</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Sun, 16 Dec 2018 16:49:51 +0000</pubDate>
      <link>https://dev.to/equinusocio/web-fonts-in-2018-321e</link>
      <guid>https://dev.to/equinusocio/web-fonts-in-2018-321e</guid>
      <description>&lt;p&gt;Custom web fonts are used everywhere around the world, but many (many and many) sites load them improperly causing a lot of problems during the page loading, like performance issues, very long loading time, blocked render and font swapped during navigation.&lt;/p&gt;

&lt;p&gt;I see many developers ignoring this argument or maybe they do the same error over and over just because "they have always done so", maybe they don't know that are working on a constantly changing environment.&lt;/p&gt;

&lt;p&gt;I just think we should break this loop and start doing the right thing in 2018 because there are just four steps to consider when loading a custom web font:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the correct font format&lt;/li&gt;
&lt;li&gt;Preload fonts&lt;/li&gt;
&lt;li&gt;Correct font-face declaration&lt;/li&gt;
&lt;li&gt;Avoid invisible text during font loading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start breaking down these points to face them one at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the correct font format
&lt;/h2&gt;

&lt;p&gt;There are many font formats that can be used on web, but only two formats are really needed if you don't have to support IE 8 or lower (&lt;a href="https://inception.davepedu.com/" rel="noopener noreferrer"&gt;wtf?!&lt;/a&gt;): &lt;strong&gt;&lt;a href="https://caniuse.com/#search=woff" rel="noopener noreferrer"&gt;woff&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://caniuse.com/#search=woff2" rel="noopener noreferrer"&gt;woff2&lt;/a&gt;&lt;/strong&gt;. These are the only two file types you should use because they are gziped by default (so they are very small) and optimised for the web, and as you can see, they are fully supported by IE 9+ and all other ever green browsers. &lt;/p&gt;

&lt;h2&gt;
  
  
  Preload fonts
&lt;/h2&gt;

&lt;p&gt;When using custom fonts you should tell the browser to preload them using the appropriate tag and &lt;code&gt;rel&lt;/code&gt; attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"font"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"fonts/cicle_fina-webfont.woff2"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"font/woff2"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"font"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"fonts/zantroke-webfont.woff2"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"font/woff2"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that the use of crossorigin here is &lt;code&gt;important&lt;/code&gt;; without this attribute, the preloaded font is ignored by the browser, and a new fetch takes place. This is because fonts are expected to be fetched anonymously by the browser, and the preload request is only made anonymous by using the this attribute.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the above example, the &lt;code&gt;rel="preload" as="font"&lt;/code&gt; attributes will ask the browser to start downloading the &lt;em&gt;required&lt;/em&gt; resource as soon as possible. They also tells the browser that this is a font, so it can appropriately prioritise it in its resource queue. Using the &lt;a href="https://developers.google.com/web/fundamentals/performance/resource-prioritization?hl=en#preload" rel="noopener noreferrer"&gt;preload hints&lt;/a&gt; will have a dramatic impact on web font performance and initial page load. Browsers that support preload and prefetch hints will start downloading web fonts as soon as they have seen the hint in the HTML file and no longer need to wait for the CSS. &lt;/p&gt;

&lt;p&gt;You can instead use the &lt;code&gt;rel="prefetch"&lt;/code&gt; attribute to tell the browser to prepare the download of the resources that may be required lately during page load or user actions so it will assign a low priority to the resource.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CAUTION:&lt;/strong&gt;&lt;br&gt;
If you’re using a CDN like Google Fonts, be sure that the font files you’re preloading match the ones in the CSS. Fonts can also be regularly updated, and if you’re preloading an old version while using the CSS for a newer one, you may end up downloading two versions of the same font and wasting your users’ bandwidth. Consider using &lt;a href="https://developers.google.com/web/fundamentals/performance/resource-prioritization?hl=en#preconnect" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;link rel="preconnect"&amp;gt;&lt;/code&gt;👨🏼‍🔬&lt;/a&gt; instead for easier maintenance.&lt;/p&gt;
&lt;h2&gt;
  
  
  Correct font-face declaration
&lt;/h2&gt;

&lt;p&gt;Declaring a font-face family is very simple but we must care about some things when we do it. Here a correct example declaring a custom font family:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Custom Font'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;font-display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Read next point */&lt;/span&gt;
  &lt;span class="py"&gt;unicode-range&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;U&lt;/span&gt;&lt;span class="err"&gt;+&lt;/span&gt;&lt;span class="m"&gt;000-5&lt;/span&gt;&lt;span class="n"&gt;FF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Download only latin glyphs */&lt;/span&gt;
  &lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'Custom Font'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="sx"&gt;url('/fonts/custom-font.woff2')&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'woff2'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
       &lt;span class="sx"&gt;url('/fonts/custom-font.woff')&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'woff'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Unicode range from &lt;a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization?hl=en#unicode-range_subsetting" rel="noopener noreferrer"&gt;Google Web Fundaments&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see we use only optimised fonts (&lt;strong&gt;woff&lt;/strong&gt; and &lt;strong&gt;woff2&lt;/strong&gt;) and we tell the browser to download only the required glyphs range (from &lt;code&gt;U+000&lt;/code&gt; to &lt;code&gt;U+5FF&lt;/code&gt;). There are also two more things to notice, the &lt;code&gt;local()&lt;/code&gt; function and the fonts order. The first one allows users to use their local copy of the font if present (eg. think about the Roboto fonts that are pre-installed on android) instead of downloading it. The fonts declaration order is also important because the browser will start to fetching the resources following the declaration order. If it support the woff2 format it will download the font, instead if it doesn't recognise the resource format it will proceed to the next one, and so on. &lt;em&gt;If you really want to use also &lt;code&gt;eot&lt;/code&gt; and &lt;code&gt;ttf&lt;/code&gt; fonts make sure to add them at the end of the &lt;code&gt;src&lt;/code&gt; declaration.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://codepen.io/elifitch/pen/Ljqway" rel="noopener noreferrer"&gt;Glyphs range generator&lt;/a&gt; by Eli Fitch&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range" rel="noopener noreferrer"&gt;&lt;code&gt;unicode-range&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://transfonter.org" rel="noopener noreferrer"&gt;Modern Font Face generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Avoid invisible text during font loading
&lt;/h2&gt;

&lt;p&gt;Fonts are often large files that take awhile to load even when gziped. To deal with this, some browsers hide text until the font loads (the "flash of invisible text"). You can avoid the "flash" and show content to users immediately using a system font then replace it.&lt;/p&gt;

&lt;p&gt;In the previous &lt;code&gt;@font-face&lt;/code&gt; example you can notice the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display" rel="noopener noreferrer"&gt;&lt;code&gt;font-display&lt;/code&gt;&lt;/a&gt; declaration. The &lt;code&gt;swap&lt;/code&gt; value tells the browser that text using this font should be displayed immediately using a system font. Once the custom font is ready, the system font is swapped out.&lt;/p&gt;

&lt;p&gt;If a &lt;a href="https://caniuse.com/#search=font-display" rel="noopener noreferrer"&gt;browser does not support&lt;/a&gt; &lt;code&gt;font-display&lt;/code&gt; it continues to follow its default behaviour for loading fonts.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Browser&lt;/th&gt;
&lt;th&gt;Default behaviour if font is not ready…&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img width="48" alt="Microsoft Edge" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.rawgit.com%2Falrra%2Fbrowser-logos%2F2109c114%2Fsrc%2Fedge%2Fedge_48x48.png" title="💩" height="48"&gt;&lt;/td&gt;
&lt;td&gt;Uses a system font until font is ready. Swaps out font.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img width="800" alt="Google Chrome" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.rawgit.com%2Falrra%2Fbrowser-logos%2F2109c114%2Fsrc%2Fchrome%2Fchrome_48x48.png" height="400"&gt;&lt;/td&gt;
&lt;td&gt;Will hide text for up to 3 seconds. If text is still not ready, uses a system font until font is ready. Swaps out font.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img width="48" alt="Firefox" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.rawgit.com%2Falrra%2Fbrowser-logos%2F2109c114%2Fsrc%2Ffirefox%2Ffirefox_48x48.png" height="48"&gt;&lt;/td&gt;
&lt;td&gt;Will hide text for up to 3 seconds. If text is still not ready, uses a system font until font is ready. Swaps out font.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img width="48" alt="Safari" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.rawgit.com%2Falrra%2Fbrowser-logos%2F2109c114%2Fsrc%2Fsafari%2Fsafari_48x48.png" title="💩" height="48"&gt;&lt;/td&gt;
&lt;td&gt;Hides text until font is ready.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Here the link to test the "standard version" and the optimised one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fontface-test.glitch.me" rel="noopener noreferrer"&gt;Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fontface-test.glitch.me/index-cool.html" rel="noopener noreferrer"&gt;Optimised&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Result
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DEFAULT&lt;/strong&gt;&lt;br&gt;
&lt;a href="//images.ctfassets.net/gz0sygvqczyz/Jj9itpvLMI6WC2m0gGEy0/2aeaef6adc66f7f769e3e4e23cb68970/standard.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/gz0sygvqczyz/Jj9itpvLMI6WC2m0gGEy0/2aeaef6adc66f7f769e3e4e23cb68970/standard.png" alt="standard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OPTIMISED&lt;/strong&gt;&lt;br&gt;
&lt;a href="//images.ctfassets.net/gz0sygvqczyz/12OTKvbLRyoEsYSq8KqcKe/96ded21bde16f3f2d94d32a76e3c9e7a/opt.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/gz0sygvqczyz/12OTKvbLRyoEsYSq8KqcKe/96ded21bde16f3f2d94d32a76e3c9e7a/opt.png" alt="opt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqkqo5fwllj57ce64btm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqkqo5fwllj57ce64btm.png" width="500" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>showdev</category>
      <category>fonts</category>
      <category>performance</category>
    </item>
    <item>
      <title>Making a CSS blob</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Mon, 22 Oct 2018 10:42:10 +0000</pubDate>
      <link>https://dev.to/equinusocio/making-a-css-blob-37nb</link>
      <guid>https://dev.to/equinusocio/making-a-css-blob-37nb</guid>
      <description>&lt;p&gt;Some days ago i was trying to make an animated blob using just the CSS as a personal experiment and research. The big issue with the blob was the curvy-shape that was should randomly morph with a slow animation.&lt;/p&gt;

&lt;p&gt;The only way i found to make this kind of transformation is using the multi-step &lt;code&gt;border-radius&lt;/code&gt; values that allow you have more controls over the edge of the element.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ltdt2tv9r6gvufbatew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ltdt2tv9r6gvufbatew.png" width="800" height="597"&gt;&lt;/a&gt;&lt;br&gt;
Image from &lt;a href="https://medium.com/9elements/css-border-radius-can-do-that-d46df1d013ae" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First I needed to read more informations about the multi step border-radius, and &lt;a href="https://css-tricks.com/almanac/properties/b/border-radius/" rel="noopener noreferrer"&gt;this&lt;/a&gt; css-tricks article was perfect. So i started writing code to prepare all the things but i noticed immediately that handling the multi values border radius was not so easy as I expected. After a bit of googling I came on &lt;a href="https://medium.com/9elements/css-border-radius-can-do-that-d46df1d013ae" rel="noopener noreferrer"&gt;this article&lt;/a&gt; and their awesome tool. This helped me to learn more about this approach and generating the values of the &lt;code&gt;border-radius&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;By adding a bit of movement and colours I got what i wanted. Here you can check the final result.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/equinusocio/embed/jezBdZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;h1&gt;
  
  
  Follow me to get more about CSS tricks!
&lt;/h1&gt;
&lt;h3&gt;
  
  
  &lt;a href="https://equinsuocha.io" rel="noopener noreferrer"&gt;https://equinsuocha.io&lt;/a&gt;
&lt;/h3&gt;
&lt;/blockquote&gt;

</description>
      <category>css</category>
      <category>animations</category>
      <category>keyframes</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Smart animations with custom properties</title>
      <dc:creator>Mattia Astorino</dc:creator>
      <pubDate>Tue, 16 Oct 2018 10:52:28 +0000</pubDate>
      <link>https://dev.to/equinusocio/smart-animations-with-custom-properties-18em</link>
      <guid>https://dev.to/equinusocio/smart-animations-with-custom-properties-18em</guid>
      <description>&lt;p&gt;A few days ago I was talking with a friend about the most popular CSS libraries to integrate simple animations into a project. After a bit of research these names emerged, including the most popular &lt;strong&gt;Animate.css&lt;/strong&gt; and &lt;strong&gt;AnimeJS&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Animate.css&lt;/strong&gt; - &lt;a href="https://daneden.github.io/animate.css/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://daneden.github.io/animate.css/" rel="noopener noreferrer"&gt;https://daneden.github.io/animate.css/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Animejs&lt;/strong&gt; - &lt;a href="http://animejs.com/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="http://animejs.com/" rel="noopener noreferrer"&gt;http://animejs.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Magic animations&lt;/strong&gt; - &lt;a href="https://www.minimamente.com/example/magic_animations/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://www.minimamente.com/example/magic_animations/" rel="noopener noreferrer"&gt;https://www.minimamente.com/example/magic_animations/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hover&lt;/strong&gt; - &lt;a href="http://ianlunn.github.io/Hover/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="http://ianlunn.github.io/Hover/" rel="noopener noreferrer"&gt;http://ianlunn.github.io/Hover/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anijs&lt;/strong&gt; - &lt;a href="http://anijs.github.io/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="http://anijs.github.io/" rel="noopener noreferrer"&gt;http://anijs.github.io/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What amazed me most is that some of these libraries, especially those CSS, were introduced several years ago. Although CSS now allows us to find better results and write simpler and more efficient code, these libraries seem timeless (do you remember jQuery?) and only few people really give importance to the complexities that these bring with them once included into our project; especially if we have to take into account weight and performance. For example, a question that we should all ask ourselves, is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does it make sense to include the entire library if I need only 3 animations?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer is obviously &lt;em&gt;no&lt;/em&gt;, and to overcome this, some people "copy" (👮🏻) the individual keyframes and use them independently from the library itself. If you use &lt;a href="https://postcss.org/" rel="noopener noreferrer"&gt;PostCSS&lt;/a&gt; (and you should) there is a plugin that allows you to conditionally import the keyframes you want, when you need them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Almost all of these CSS libraries provide a set of classes to which a specific animation is assigned. So, to apply a &lt;em&gt;fade from bottom&lt;/em&gt; animation we will add the relative class to the HTML element, then customising it through CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;progress&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fadeFromBottom"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/progress&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.fadeFromBottom&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;animation-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* This may require !important 👀 */&lt;/span&gt;
    &lt;span class="nl"&gt;animation-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As is easily to understand, this means that for each imported animation (for example, the direction is managed with a different class) there is a corresponding CSS class and to customise it we must overwrite the code, sometime using the &lt;em&gt;!important&lt;/em&gt; (❗️) keyword, resulting in a not-so-much scalable code.&lt;/p&gt;

&lt;p&gt;How can we therefore evolve this approach using today's tools?&lt;/p&gt;

&lt;h2&gt;
  
  
  Continue reading on:
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://equinsuocha.io/blog/smart-animations-with-custom-properties" rel="noopener noreferrer"&gt;Smart animations with custom properties - Equinsuocha.io&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>showdev</category>
      <category>css</category>
      <category>animations</category>
    </item>
  </channel>
</rss>
