⭐ If you would like to buy me a coffee, well thank you very much that is mega kind! : https://www.buymeacoffee.com/honeyvig Hire a web Developer and Designer to upgrade and boost your online presence with cutting edge Technologies

Friday, July 28, 2023

Writing CSS In 2023: Is It Any Different Than A Few Years Ago?

 CSS is evolving faster than ever. With all of the new features that are now available — and forthcoming — since we got Flexbox and Grid years ago, the way we write CSS is evolving.

 

Is there anything in the front-end world that’s evolving faster than CSS these days? After what seemed like a long lull following blockbusters Flexbox and Grid, watching CSS release new features over the past few years has been more like watching a wild game of rugby on the telly. The pace is exciting, if not overwhelming at the same time.

But have all these bells and whistles actually changed the way you write CSS? New features have certainly influenced the way I write CSS today, but perhaps not quite as radically as I would have expected.

And while I’ve seen no shortage of blog posts with high-level examples and creative experiments of all these newfangled things that are available to us, I have yet to see practical applications make their way into production or everyday use. I remember when Sass started finding its way into CSS tutorials, often used as the go-to syntax for code examples and snippets. I’m not exactly seeing that same organic adoption happen with, say, logical properties, and we’ve had full browser support for them for about two years now.

This isn’t to rag on anyone or anything. I, for one, am stoked beyond all heck about how CSS is evolving. Many of the latest features are ones we have craved for many, many years. And indeed, there are several of them finding their way into my CSS. Again, not drastically, but enough that I’m enjoying writing CSS more now than ever.

Let me count the ways.

More And More Container Queries #

I’ll say it: I’ve never loved writing media queries for responsive layouts. Content responds differently to the width of the viewport depending on the component it’s in. And balancing the content in one component has always been a juggling act with balancing the content in other components, adding up to a mess of media queries at seemingly arbitrary breakpoints. Nesting media queries inside a selector with Sass has made it tolerable, but not to the extent that I “enjoyed” writing new queries and modifying existing ones each time a new design with UI changes is handed to me.

Container queries are the right answer for me. Now I can scope child elements to a parent container and rely on the container’s size for defining where the layout shifts without paying any mind to other surrounding components.

The other thing I like about container queries is that they feel very CSS-y. Defining a container directly on a selector matches a natural property-value syntax and helps me avoid having to figure out math upfront to determine breakpoints.

.parent {
  container-type: inline-size;
}

@container (min-width: 600px) {
  .child {
    align-self: center;
  }
}

I still use media queries for responsive layouts but tend to reserve them for “bigger” layouts that are made up of assembled containers. Breakpoints are more predictable (and can actually more explicitly target specific devices) when there’s no need to consider what is happening inside each individual container.

Learn About Container Queries #

More after jump! Continue reading below ↓

Grouping Styles In Layers #

I love this way of managing the cascade! Now, if I have a reset or some third-party CSS from a framework or whatever, I can wrap those in a cascade layer and chuck them at the bottom of a file so my own styles are front and center.

I have yet to ship anything using cascade layers, but I now reach for them for nearly every CodePen demo I make. The browser support is there, so that’s no issue. It’s more that I still rely on Sass on projects for certain affordances, and maintaining styles in partialized files still feels nice to me, at least for that sort of work.

But in an isolated demo where all my styles are in one place, like CodePen? Yeah, all the cascade layers, please! Well, all I really need is one layer for the base styles since un-layered styles have higher specificity than layered ones. That leaves my demo-specific styles clean, uncluttered, and still able to override the base at the top, which makes it way more convenient to access them.

body {
  display: grid;
  gap: 3rem;
  place-items: center;
}

@layer base {
  body {
    font-size: 1.25rem;
    line-height: 1.35;
    padding: 3rem;
  }
}

Learn More About Cascade Layers #

:is() And :where() #

I definitely reach for these newer relational pseudo-selectors, but not really for the benefits of selecting elements conditionally based on relationships.

Instead, I use them most often for managing specificity. But unlike cascade layers, I actually use these in production.

Why? Because with :is(), specificity is determined not by the main selector but by the most specific selector in its argument list.

/* Specificity: 0 1 1 */
:is(ol, .list, ul) li {}

/* Specificity: 0 0 2 */
ol li {}

The .list selector gives the first ruleset a higher specificity score meaning it “beats” the second ruleset even though the first ruleset is higher in the cascade.

On the flip side, the specificity of :where() is a big ol’ score of zero, so it does not add to the overall score of whatever selector it’s on. It simply doesn’t matter at all what’s in its argument list. For the same reason I use :is() to add specificity, I use :where() to strip it out. I love keeping specificity generally low because I still want the cascade to operate with as little friction as possible, and :where() makes that possible, especially for defining global styles.

A perfect example is wrapping :not() inside :where() to prevent :not() from bumping up specificity:

/* Specificity: 0 0 0 */
:where(:not(.some-element)) {}

Taken together, `:is()` and `:where()` not only help manage specificity but also take some cognitive load from “naming” things.

I’m one of those folks who still love the BEM syntax. But naming is one of the hardest things about it. I often find myself running out of names that help describe the function of an element and its relationship to elements around it. The specificity-wrangling powers of :is() and :where() means I can rely less on elaborate class names and more on element selectors instead.

Learn More About :is() And :where() #

The New Color Function Syntax #

The updated syntax for color functions like rgb() and hsl() (and the evolving oklch() and oklab()) isn’t the sort of attention-grabbing headline that leads to oo’s and aw’s, but it sure does make it a lot better to define color values.

For one, I never have to reach for rgba() or hsla() when I need an alpha value. In fact, I always used those whether or not I needed alpha because I didn’t want to bother deciding which version to use.

color: hsl(50deg, 100%, 50%);

/* Same */
color: hsla(50deg, 100%, 50% / 1)

Yes, writing the extra a, /, and 1 was worth the cost of not having to think about which function to use.

But the updated color syntax is like a honey badger: it just doesn’t care. It doesn’t care about the extra a in the function name. It doesn’t even care about commas.

color: hsl(50deg 100% 50% / .5);

So, yeah. That’s definitely changed the way I write colors in CSS.

What I’m really excited to start using is the newer oklch() and oklab() color spaces now that they have full browser support!

Learn More About CSS Color 4 Features #

Sniffing Out User Preferences #

I think a lot of us were pretty stoked when we got media queries that respect a user’s display preferences, the key one being the user’s preferred color scheme for quickly creating dark and light interfaces.

:root {
  --bg-color: hsl(0deg 0% 100%);
  --text-color: hsl(0deg 0% 0%);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg-color: hsl(0deg 0% 0%);
    --text-color: hsl(0deg 0% 100%);
  }
}

body {
  background: var(--bg-color);
  color: var(--text-color);
}

But it’s the prefers-reduced-motion query that has changed my CSS the most. It’s the first thing I think about any time a project involves CSS animations and transitions. I love the idea that a reduced motion preference doesn’t mean nuking all animation, so I’ll often use prefers-reduced-motion to slow everything down when that’s the preference. That means I have something like this (usually in a cascade layer for base styles):

@layer base {
  :root {
    --anim-duration: 1s;
  }

  /* Reduced motion by default */
  body {
    animation-duration: --anim-duration;
    transition: --anim-duration;
  }

  /* Opt into increased motion */
  @media screen and (prefers-reduced-motion: no-preference) {
    body {
      --anim-duration: .25s;
    }
  }
}

Learn More About User Preference Queries #

Defining Color Palettes #

I’ve used variables for defining and assigning colors ever since I adopted Sass and was thrilled when CSS custom properties came. I’d give generic names to the colors in a palette before passing them into variables with more functional names.

/* Color Palette */
--red: #ff0000;
/* etc. */

/* Brand Colors */
--color-primary: var(--red);
/* etc. */

I still do this, but now I will abstract things even further using color functions on projects with big palettes:

:root {
  /* Primary Color HSL */
  --h: 21deg;
  --s: 100%;
  --l: 50%;
  
  --color-primary: hsl(var(--h) var(--s) var(--l) / 1);
}

.bg-color {
  background: var(--color-primary);
}

.bg-color--secondary {
  --h: 56deg;
  background: hsl(var(--h) var(--s) var(--l) / 1);
}

A little too abstract? Maybe. But for those projects where you might have ten different varieties of red, orange, yellow, and so on, it’s nice to have this level of fine-grained control to manipulate them. Perhaps there is more control with color-mix() that I just haven’t explored yet.

Learn More About Defining Color Palettes #

What I’m Not Using #

Huh, I guess I am writing CSS a bit differently than I used to! It just doesn’t feel like it, but that probably has to do with the fact that there are so many other new features I am not currently using. The number of new features I am using is much, much lower than the number of features I have yet to pick up, whether it’s because of browser support or because I just haven’t gotten to it yet.

CSS Nesting #

I’m really looking forward to this because it just might be the tipping point where I completely drop Sass for vanilla CSS. It’s waiting for Firefox to support it at the time of this writing, so it could be right around the corner.

Style Queries #

I’ve made no secret that applying styles to elements based on the styles of other elements is something that I’m really interested in. That might be more of an academic interest because specific use cases for style queries elude me. Maybe that will change as they gain browser support, and we see a lot more blog posts where smart folks experiment with them.

:has() #

I’ll definitely use this when Firefox supports it. Until then, I’ve merely tinkered with it and have enjoyed how others have been experimenting with it. Without full support, though, it hasn’t changed the way I write CSS. I expect that it will, though, because how can having the ability to select a parent element based on the child it contains be a bad thing, right?

Dynamic Viewport Units #

I’ve started sprinkling these in my styles since they gained wide support at the end of 2022. Like style queries, I only see limited use cases — most notably when setting elements to full height on a mobile device. So, instead of using height: 100vh, I’m starting to write height: 100dvh more and more. I guess that has influenced how I write CSS, even if it’s subtle.

Media Query Range Syntax #

Honestly, I just haven’t thought much about the fact that there’s a nicer way to write responsive media queries on the viewport. I’m aware of it but haven’t made it a part of my everyday CSS for no other reason than ignorance.

OKLCH/OKLAB Color Spaces #

oklch() will most definitely be my go-to color function. It gained wide support in March of this year, so I’ve only had a couple of months and no projects to use it. But given the time, I expect it will be the most widely used way to define colors in my CSS.

The only issue with it, I see, is that oklch() is incompatible with another color feature I’m excited about…

color() #

It’s widely supported now, as of May 2023! That’s just too new to make its way into my everyday CSS, but you can bet that it will. The ability to tap into any color space — be it sRGB, Display P3, or Rec2020 — is just so much nicer than having to reach for a specific color function, at least for colors in a color space with RGB channels (that’s why color() is incompatible with oklch() and other non-RGB color spaces).

--primary-color: color(display-p3 1 0.4 0);

I’m not in love with RGB values because they’re tough to understand, unlike, say, HSL. I’m sure I’ll still use oklch() or hsl() in most cases for that very reason. It’s a bummer we can’t do something like this:

/* 👎 */
--primary-color: color(oklch 70% 0.222 41.29);

We have to do this instead:

/* 👍 */
--primary-color: oklch(70% 0.222 41.29);

The confusing thing about that is it’s not like Display P3 has its own function like OKLCH:

/* 👎 */
--primary-color: display-p3(1 0.434 0.088);

We’re forced to use color() to tap into Display P3. That’s at odds with OKLCH/OKLAB, where we’re forced to reach for those specific functions.

Maybe one day we’ll have a global color() function that supports them all! Until then, my CSS will use both color() and specific functions like oklch() and decide which is best for whatever I’m working on.

I’ll also toss color-mix() in this bucket, as it gained full support at the same time as color(). It’s not something I write regularly yet, but I’ll certainly play with it, likely for creating color palettes.

Honorable Mentions #

It would be quite a feat to comment on every single new CSS feature that has shipped over the past five or so years. The main theme when it comes to which features I am not using in my day-to-day work is that they are simply too new or they lack browser support. That doesn’t mean I won’t use them (I likely will!), but for the time being, I’m merely keeping a side-eye on them or simply having a fun time dabbling in them.

Those include:

  • Trigonometric functions,
  • Anchor position,
  • Scroll-linked animations,
  • initial-letter,
  • <selectmenu> and <popover>,
  • View transitions,
  • Scoped Styles.

What about you? You must be writing CSS differently now than you were five years ago, right? Are you handling the cascade differently? Do you write more vanilla CSS than reaching for a preprocessor? How about typography, like managing line heights and scale? Tell me — or better yet, show me — how you’re CSS-ing these days.

Designing Age-Inclusive Products: Guidelines And Best Practices

 With an estimated one in every eight individuals worldwide surpassing the age of 60, who are actively adopting online shopping, the need for user-friendly interfaces tailored to their needs becomes apparent. Explore the guidelines to help you design inclusive products for all, particularly for an older audience and your future self.

Why is it so important to take into account older adults? One person in eight on the planet is over 60, and they are more online than ever. Approximately one billion people aged 60+ are alive today. Most of them are healthy and active and have discretionary income. Moreover, it is growing faster than any other age group and is projected to be 20% of the world’s population (~2 billion people) by 2050. They are also the fastest-growing category of e-commerce shoppers.

Older people today are adopting technology more than ever before. From the use of the Internet, smartphones, tablets, and wearables to smart TVs and speakers, a growing number of older people are users. Ownership of smartphones, for example, increased from 70% to 77% among the 50+ population in the United States between 2017 and 2021. Moreover, during the Covid-19 pandemic, there was a significant rise in older adults’ motivation to use digital technology.

However, many older people still lack sufficient Internet connectivity or technological skill to use devices and consume digital services. It is estimated that two in five feel technology is not designed for them (PDF).

Opportunity To Integrate Older people Into The Digital World #

More and more aspects of life are conducted on digital platforms: interpersonal communication, banking, healthcare, personal consumption, and exercising one’s rights are just some of them. Therefore, digital platforms that are challenging to use for older people have a negative impact on their quality of life. It prevents them from accessing essential services and integrating equally into society.

According to the inclusive design approach, one should take into account the needs of as many users as possible without stigmatizing or excluding a specific group by designing niche products.

If you adopt this principle, you can design a digital platform that serves a wide range of people, not just those aged 65+. Usually, a service that meets the needs of people aged 65+ will serve other audiences as well.

Adopting Age-appropriate Navigation And Orientation Practices #

Advancing age can also bring with it a decrease in the rate of information processing, whether in understanding, thinking, or remembering. Plus, the ability to ignore distractions, focus on one stimulus, and perform several complex actions simultaneously also decreases.

Additionally, due to their age, some suffer from a decrease in executive functions that enable planning, executing, and delaying reactions. Therefore, there is a higher chance they will perform random actions such as clicking on unintended places, closing pages, or making errors when using apps. Some may have difficulty understanding that icons carry the same meaning across different apps or in dealing with situations that do not correspond with their expectations of the digital world. Despite such difficulties, it is essential to stress that the ability to learn from feedback — for example, via affirmations — does not diminish with age.

What Should We Do If We Want To Increase Their Engagement? #

Here are a few guidelines to help you design a more inclusive product. Those guidelines can increase the usage of younger users but are highly crucial for older users:

Minimize The Number Of Required Actions And Create Shortcuts #

Some people over 65 find it challenging to cope with information overload and multiple options.

Proper information architecture and hierarchy will indicate what is important to the user and require less effort. We should ensure that the required actions appear immediately and easily so that the user does not have to search for them. Some important ones to mention are white space, content placement, space, language, number of actions, and others. Below are these and some others listed with explanations:

  • White space
    Reducing the number of elements on a screen, increasing the spacing between them, and retaining whitespace will make the screen feel less crowded and, therefore, clearer and more inviting. The added value is in the feeling of simplicity it creates. This improves the user’s sense of competence and ability to focus. Clear typography following one of the established typographic scales is relevant for websites, apps, and complex data systems.
A screenshot of the Bank of America website with many visual elements
The Bank of America website has a lot of visual elements that can be overwhelming and may make it difficult for users to feel competent and focused. (Large preview)
The homepage of the Silicon Valley bank website
The homepage of the Silicon Valley bank website has been streamlined to make it easier for users to access their accounts by reducing the number of elements on the page. (Large preview)
  • Dialog box
    A limited number of options prevents cognitive overload. Therefore, conduct a careful mapping of the digital platform, distilling out the most important actions and contents.
  • Central placement
    The most important themes should be positioned at the center of the screen.
  • Large & spacious
    The most important buttons should be enlarged and positioned prominently to allow immediate recognition.
  • Clear language
    Topics should be clearly labeled, and the labels should be verified in usability testing. Complicated terms should be avoided since they might not be familiar to the target audience.
  • Limited number of actions
    The number of steps (clicks and scrolls) necessary to achieve a goal should be minimized.
  • Shortcuts and multiple/redundant paths
    Make it easy for users to reach their goals by providing multiple options, such as Quick Links, as seen in the example below.
A screenshot of the Google search result with Mediamarkt.de on top with available quick links
(Large preview)
More after jump! Continue reading below ↓

What To Know About Navigation & Orientation? #

Some people aged 65+ can experience a decline in memory recall. Some are also unfamiliar with the principles of the digital world. Therefore, to enhance their sense of control, the following principles should be adopted: rely on recognition, not memory; allow going back; design clear navigation keys; be consistent in design and operation; and provide indicators. Below we will discuss several principles to facilitate navigation.

  • Recognition, not memory
    This principle means creating an interface where users do not have to use their memory to recall information. Instead, they will be asked to identify familiar and prominent components, such as quick access to previously visited pages or actions. The illustration below is an example of how Korea’s post office presents the main tasks on the main screen in a way that doesn’t require memory but recognition. Additional support is the use of color to help the users recognize how to navigate the site once they return to it.
Korea’s post office website
Source: koreapost.go.kr. (Large preview)
  • Indicators and feedback:
    • Emphasize the performed actions: Use breadcrumbs to indicate which links or buttons the user has clicked on and their location.
    • Create a conspicuous and permanent back icon that takes the user to a previous page/stage. This is in addition to the browser’s back and homepage icons.
    • Clear and prominent navigation buttons: Emphasize navigation buttons and add text to explain their function.
  • Consistency
    Create an ongoing, consistent user experience using recurring items. Allow the users to learn the interface, generating a sense of success and building anticipation for the next stage. Pay attention to the location and design of fixed buttons that have the same function.
  • Progress
    Create obvious hints, such as a progress bar, that help users to understand where they are in the process.
  • Success & mistakes
    Highlight progress and successful actions. Additionally, indicate errors clearly and provide ways for easy recovery.
  • Contact Us
    Choose a prominent location for the help options. Provide contact information using various channels, e.g., telephone number and email address.

Choosing components with an age-inclusive mindset can change our day-to-day decisions and allow us to create an easy-to-operate interface.

The following guidelines relate to changes in motor functions.

Example of HMO website
Example of HMO website taken from the LOG IN guide — toolkit on increasing the usage of digital platforms, services and products by older people. (Large preview)

Creating An Interface That Is Easy To Operate #

As age increases, it may be accompanied by difficulty in touching a specific spot accurately, regulating a click’s intensity, or performing quick actions, such as double-clicking. Therefore, the following principles should be ensured: space out the keys, avoid the need for a high degree of precision, avoid gestures requiring sensory regulation, and enable users to progress at their own pace.

  • Large & spacious
    Design large and well-spaced elements.
  • Individual pace:
    • When creating pop-up/toast messages, allow users to initiate closing or at least leave the messages visible for longer for slower readers.
    • Avoid menus that open on hover. Always use click-tap menus instead.
  • Indication
    Provide clear scroll indicators (e.g., side arrows). Reduce the need for precision: Avoid small clicking areas, mouse hovering, and double-clicking.
  • Ensure that the interface is responsive on all screens.
    For touch screens:
    • Click actions should not rely on touch intensity or precision.
    • Avoid, as much as possible, long strokes and drag gestures, and reduce scroll options. At the very least, provide clear indication and instruction, and offer alternatives, such as an arrow or button directing to specific places.
    • Avoid the need for very precise actions, such as in small clicking areas, and try to keep to the minimum size for comfortable tapping/clicking of at least 44x44 px.
    • Avoid actions requiring fine motor regulation such as spread, pinch, and rotate.
Example of login forms
Example of login forms taken from the LOG IN guide — toolkit on increasing the usage of digital platforms, services and products by older people. (Large preview)

Let’s examine the homepage of three famous e-commerce websites in the eyes of an older user without going into details.

Aliexpress website with visual overload
(Large preview)

Aliexpress website, as seen in the image above, is a good example of an “unfriendly” website — it suffers from visual overload. Too many buttons and tags are emphasized, which makes it hard to focus older user attention. Moreover, given the visual overload, the side menu is easy to ignore, and many users will be required to use the search bar, which needs to be more dominant and rely on their recall of items, not recognition.

On the Amazon website (see the image below), the size of each category image may be distracting, requiring the user to scroll a lot and challenging his ability to navigate.

Amazon website with different in sizes category images
(Large preview)

In contrast with these previous sites, eBay does better regarding visual overload; the dominance of the search bar and even the menu placement make it easier for older users to navigate.

eBay website with good navigation
(Large preview)

Wrapping Up #

Every designer would probably state that they want their website and app to be inclusive, easy to navigate, and user-friendly. Yet, as we have seen in our examples above, we need to create awareness to integrate details that would make it easier for older users to navigate the Internet. As we age, all of us will experience longer reaction times, changes in selective attention, attention-splitting, and changes in our motor functions. Therefore, designing for an older audience will achieve the goals of having an inclusive, easy-to-navigate, and user-friendly for our future selves as well.

To sum up, in order to create an easy operation and orientation of an interface, we should pay attention to the following:

  • Large, spaced-out objects;
  • Operation does not require fine gestures and precision;
  • A minimum number of actions to achieve goals;
  • The user should control the rate of progress;
  • Reassuring notifications upon successful actions;
  • Consistency of design and operation;
  • Minimizing the number of choices the user must make;
  • Highlighting the actions performed by the user.

The article is based on one of the chapters of the Log In guide. The guide was created within the framework of the National Initiative to Promote Digital Literacy Among Older Adults, which is a partnership between the Israel National Digital Agency and JDC-ESHEL.