🔥 (#211) Special CSS pseudo-selectors, performance tracing, and aria roles

Read this on my blog

Hey!

The Mastering Nuxt launch has been going well!

We added a bunch of new lessons yesterday, with more coming weekly until the course is finished. We're now at 2+ hours of content (I expect about 5 in total).

I also got sick over the weekend and lost my voice, so I'm doing all the non-recording things I can until my vocal cords are healed.

— Michael

🔥 Special CSS pseudo-selectors in Vue

If you want some styles to apply specifically to slot content, you can do that with the :slotted pseudo-selector:

<style scoped>    /* Add margin to <p> tags within the slot */    :slotted(p) {      margin: 15px 5px;    }  </style>

You can also use :global to have styles apply to global scope, even within the

<style scoped>    :global(body) {      margin: 0;      padding: 0;      font-family: sans-serif;    }  </style>

Of course, if you have lots of global styles you want to add, it's probably easier to just add a second <style>

<style scoped>    /* Add margin to <p> tags within the slot */    :slotted(p) {      margin: 15px 5px;    }  </style>    <style>    body {      margin: 0;      padding: 0;      font-family: sans-serif;    }  </style>

Check out the docs for more info.

🔥 Performance Tracing

Vue allows you to do performance tracing to help you debug any performance issues:

const app = createApp({});  app.config.performance = true;

Once you do this, you can use the official Vue Devtools to debug your app's performance.

🔥 Aria roles you didn't know you needed

Aria roles are used to tell a screenreader what an element is for.

This is really important when the native HTML element just doesn't exist (eg. roles like toolbar and alert) or when you're using a different HTML element for design or technical reasons (eg. wrapping a radio button to style it).

But please, remember that you should always use the semantic element where you can. This is always the best and most effective solution.

There are six different categories of aria roles:

  • Widget - roles like button, checkbox, separator, tab, or scrollbar
  • Composite - roles like combobox and listbox (these are for dropdown menus), radiogroup, or tree
  • Document structure - this includes article, presentation, figure, feed, and directory
  • Landmark - banner, main, navigation, and region are roles in this category
  • Live region - alert, log, marquee, and status are roles that might update with real-time information
  • Window - alertdialog and dialog are the only two roles in this category

You can check out the full list here: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#roles

🎙️ #053 — New Releases: Nuxt 3.16 and Nuxt UI 3

Nuxt 3.16 dropped and it's packed with goodies!

In this episode, Alex and Michael break down all the cool stuff in this release that'll make your Nuxt development smoother.

They dive into the new command to initialize a Nuxt application, the performance-game-changing lazy hydration support that'll boost your app's performance, and named layer aliases (that you've been waiting for). Plus, huge performance improvements, better error messages with Nitro 2.11 and debugging improvements that'll save you hours of head-scratching.

But wait, there's more!

The duo also geeks out over Nuxt UI v3, which (surprise!) now works with plain Vue.js too - not just Nuxt. Learn how it leverages Tailwind v4, introduces a sweet CSS variables-based design system, and builds on Reka UI primitives for better accessibility. And somehow, a discount code for Nuxt UI Pro cough DEJAVUE cough* gets snuck in there too!

Watch on YouTube or listen on your favorite podcast platform.

Chapters:

In case you missed them:

📜 How to Redirect in Nuxt (Every Single Way)

There are a lot of different ways to redirect users in Nuxt, each with their own use cases.

In this (very detailed!) article I explore the different ways to redirect users in Nuxt, giving examples of when each might be useful.

Check it out here: How to Redirect in Nuxt (Every Single Way)

📜 The Extract Conditional Pattern in Vue

An extremely common question I get asked all the time is, "how do you know when to split up a component?"

I want to share a simple pattern with you that is basically fool-proof, and can be applied to lots of components with almost no thought.

Check it out here: The Extract Conditional Pattern in Vue

📅 Upcoming Events

Here are some upcoming events you might be interested in. Let me know if I've missed any!

VueConf US 2025 — (May 13, 2025 to May 15, 2025)

Giving a talk here on component patterns! A great Vue conference, this year held in Tampa. Two days of conference talks, plus a day for workshops.

Check it out here

MadVue 2025 — (May 29, 2025)

It's time to get together in Madrid. Join for a full day of talks, activities, and networking with the Vue.js community and ecosystem.

Check it out here

💬 Better Not Start

"Programming is just saying "I have a meeting in an hour so better not start on this yet" to yourself until you die." — Alex Engelberg

🧠 Spaced-repetition: Nuxt Plugin Dependencies

The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬

Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.

When writing plugins for Nuxt, you can specify dependencies:

export default defineNuxtPlugin({    name: 'my-sick-plugin-that-will-change-the-world',    dependsOn: ['another-plugin']    async setup (nuxtApp) {      // The setup is only run once `another-plugin` has been initialized    }  })

But why do we need this?

Normally, plugins are initialized sequentially — based on the order they are in the filesystem:

plugins/  - 01.firstPlugin.ts    // Use numbers to force non-alphabetical order  - 02.anotherPlugin.ts  - thirdPlugin.ts

But we can also have them loaded in parallel, which speeds things up if they don't depend on each other:

export default defineNuxtPlugin({    name: 'my-parallel-plugin',    parallel: true,    async setup (nuxtApp) {      // Runs completely independently of all other plugins    }  })

However, sometimes we have other plugins that depend on these parallel plugins. By using the dependsOn key, we can let Nuxt know which plugins we need to wait for, even if they're being run in parallel:

export default defineNuxtPlugin({    name: 'my-sick-plugin-that-will-change-the-world',    dependsOn: ['my-parallel-plugin']    async setup (nuxtApp) {      // Will wait for `my-parallel-plugin` to finish before initializing    }  })

Although useful, you don't actually need this feature (probably). Pooya Parsa has said this:

I wouldn't personally use this kind of hard dependency graph in plugins. Hooks are much more flexible in terms of dependency definition and pretty sure every situation is solvable with correct patterns. Saying I see it as mainly an "escape hatch" for authors looks good addition considering historically it was always a requested feature.

🔗 Want more Vue and Nuxt links?

Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links.

Sign up for it here.

p.s. I also have a bunch of products/courses:

Unsubscribe

评论

此博客中的热门博文

Scripting News: Sunday, January 5, 2025