Vue 3 has a known issue where scoped styles do not get applied correctly within the content of a <slot> element

Utilizing the Oruga and Storybook libraries for creating Vue 3 components.

The code in the Vue file looks like this:

<template>
  <o-radio v-bind="$props" v-model="model">
    <slot />
  </o-radio>
</template>

<script lang="ts">
import { defineComponent } from "@vue/runtime-core";
import Radio from '../mixins/radio-mixins';

export default defineComponent({
  name: "BaseRadio",
  computed: {
    model: {
      get() {
        return this.$props.nativeValue;
      },
      set(value: any) {
        this.$emit("input", value);
      },
    },
  },
  emits: ["input"],
  props: {
    ...Radio.props,
  },
});
</script>

<style scoped>
  .b-radio.radio.is-primary .check:checked {
    border-color: var(--color-blue);
  }
  .b-radio.radio.is-primary .check:checked:focus {
    box-shadow: 0 0 3px 3px var(--color-light-blue);
  }
  .b-radio.radio.is-primary .check:before {
    background: var(--color-blue);
  }
</style>

Within the <style> tag, I am adjusting the classes provided by the Oruga library to achieve the desired styling.

The issue arises when using the scoped attribute in the <style> tag, causing none of the styles to be applied. Removing scoped allows the styles to work as intended.

Is there a way to resolve this problem? I need to apply these styles while still utilizing the scoped tag in the <style>.

Answer №1

Typically, slotted content (elements displayed with the help of the <slot> tag) remains unaffected by the scoped styles of the hosting component that contains that <slot>. Instead, that content is considered to be "owned by" its parent, which is the actual component being rendered into the <slot>.

This presents you with 3 potential options:

Embed the styles directly in the slotted component

If you include the styles within the component that is inserted into the slot, those styles will be applied to that component regardless of where it appears.

Of course, this may not always be practical or even feasible, especially if you do not have control over the content being slotted in.

Utilize the :slotted() Selector

The ::slotted() pseudo-class is specifically meant for referencing elements rendered inside a <slot> tag. Vue 3 has its own version of this feature, denoted as :slotted() (with a single colon : instead of two ::).

<style scoped>
  :slotted(.b-radio.radio.is-primary .check:checked) {
    border-color: var(--color-blue);
  }
  :slotted(.b-radio.radio.is-primary .check:checked:focus) {
    box-shadow: 0 0 3px 3px var(--color-light-blue);
  }
  :slotted(.b-radio.radio.is-primary .check:before) {
    background: var(--color-blue);
  }
</style>

Employ the :deep() Selector

While the scoped attribute confines styles to the component they belong to, the :deep() selector allows components to apply styles to their children, including slotted components since they are rendered as child nodes in the DOM.

<style scoped>
  :deep(.b-radio.radio.is-primary .check:checked) {
    border-color: var(--color-blue);
  }
  :deep(.b-radio.radio.is-primary .check:checked:focus) {
    box-shadow: 0 0 3px 3px var(--color-light-blue);
  }
  :deep(.b-radio.radio.is-primary .check:before) {
    background: var(--color-blue);
  }
</style>

However, it is worth noting that using this method could potentially extend the scope of styles down the hierarchy; grandchildren and beyond may still be influenced by these styles. Care should be taken with class names and selectors to prevent unexpected issues.

Answer №2

Perhaps the reason for this issue is that you are attempting to alter classes that are specific to the DOM due to the Oruga framework being used. By excluding the "scoped" property, you can make changes to Oruga classes globally. These Oruga classes only apply within the component itself and not in your actual code when working with the component.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for effectively eliminating errors in a redux store

Within my react-redux application, I have implemented a system to catch error responses from redux-saga. These errors are saved in the redux-store and rendered in the component. However, a major challenge arises when trying to remove these errors upon comp ...

Sinon Stub generates varying values with each invocation

I'm pretty new to TypeScript and JavaScript, but I've managed to create a functioning VScode extension that I'm really happy with. However, I'm running into some issues with my Mocha tests. Here's a snippet of the code I'm str ...

Mastering the art of column stacking with CSS on your WordPress website

Looking for a CSS solution to adjust the layout when the screen resolution is lowered. Currently, I have two rows with three columns in each row, containing blurbs. My goal is to make these two rows convert into three rows with two columns each at a cert ...

Choosing items from a list based on the choices made in another list

How can I make the second select bar dependent on the selection made in the first one? For example, if I select publisher with id=1, then only show templates that have publisher id=1. <v-flex> @can('publish') @if (sizeof($publ ...

Problem with Ext.net TabPanel

I am encountering a problem with the Ext.net TabPanel. Every time the page containing the tab panel is opened for the first time after the application has been rebuilt, it throws an error Uncaught TypeError: Object [object Object] has no method 'getCo ...

`Is there a specific location for this code snippet?`

Recently, I stumbled upon a script that enables website screen scraping. For instance, you can check out an example on JsFiddle The issue arises when I attempt to incorporate another script from "Embed.ly" This specific script enhances a provided link and ...

The border length of the unordered list is equal to half of the length

I would like the blue borders of these "ul" elements to be centered beneath the black "li" elements, with a width that is 50% of the child width. However, I'm unsure about how to achieve this. I attempted using ":before", but it only seems to work for ...

Simple steps for importing JS files in a web application

Upon examining the code snippet below: const express = require('express'); const app = express(); const http = require('http').Server(app); const io = require('socket.io')(http); const cors = require('cors'); app.u ...

Please explain this ES6 syntax to me: Using a colon after a function call

While exploring the documentation for a flux store in React, I came across an example that caught my attention. import {ReduceStore} from 'flux/utils'; class CounterStore extends ReduceStore<number> { getInitialState(): number { ret ...

What causes materialui styles to vanish upon refreshing in nextjs?

After consulting the materialui documentation (https://material-ui.com/guides/server-rendering/), I was able to find a solution, but I am still unsure of the underlying reason. Why does the style work initially during rendering but disappear upon subs ...

Ways to combine duplicate entries within a column using Ruby on Rails?

I need some help with a filtering issue related to sign names. I am trying to merge the content together if there is more than one name of the sign. You can refer to the image attached for better clarity, where I have two server names but I only want to di ...

Internet Explorer fails to account for the height of table cells when using overflow-x:auto, leading to hidden content. In contrast, Chrome adjusts for this automatically. What steps can be taken to address

Chrome: Internet Explorer: The image at the top shows how the content should appear on Chrome, while the one below demonstrates how it is displayed on IE11. The issue seems to be that on Internet Explorer, the content gets hidden and doesn't adjust ...

Customizable form fields in AngularJS

Consider the scenario of the form below: First Name: string Last Name: string Married: checkbox % Display the following once the checkbox is selected % Partner First Name: Partner Last Name: [Submit] How can a form with optional fields be created in Angu ...

Navigation Bar Search Box Alignment Problem

Hi there, I'm new to programming and I'm trying to center my search bar with the navigation links beside it within a fixed navigation bar. However, I'm having trouble getting it to work properly. Can someone take a look at my HTML and CSS co ...

Pattern matching to exclude specific characters

To enhance security measures, I am looking to restrict users from inputting the following characters: ~ " # % & * : < > ? / \ { | } . The key requirement is that all other characters should be permitted, while ensuring that only the sp ...

How to efficiently transfer data between PHP and Javascript using ajax?

Struggling greatly with the ajax function within the jQuery library. As a beginner in jQuery, ajax, and php, I am currently engaged in a school project that involves creating a game-like environment where a 10x10 table generates numbers, selects a cell aut ...

What is the best way to center my form vertically within the form container?

I am having trouble aligning my form vertically. I've experimented with different methods such as using display: table-cell and vertical-align: middle property, but nothing seems to work. I want to maintain the current structure of the page and would ...

Is there a more efficient alternative to `[].push.apply(this, arr)` for combining elements in an array instance within a constructor?

It only takes 0.15ms for this line in my constructor function to execute. [].push.apply(this, selector); I'm not satisfied with the 0.15ms execution time. I believe there must be a quicker alternative available. This particular line seems to be conv ...

What steps should I take to adjust the price when multiple items are chosen?

I am working on a school project that requires JavaScript programming assistance. You can view the code here: https://jsfiddle.net/zvov1jpr/3/ HTML: <script src="java.js"></script> <div id="formular"> <div id=&qu ...

Utilizing React JS and lodash's get method within a single function

Is it possible to display two string objects in the same line using Lodash get? Can I achieve this by chaining (_.chain(vehicle).get('test').get('test2))? Below is a snippet of the JSON file: { "results": [ { " ...