Using Vue.js: Is there a way to apply scoped CSS to dynamically generated HTML content?

Summary:

I'm struggling to apply scoped CSS styling to dynamically generated HTML in my Vue component. The generated HTML lacks the necessary data attribute for scoping, making it difficult to style with scoped CSS rules.

Details:

In a function called highlight, I create an HTML string that highlights occurrences of a search term by wrapping them in <span class="match"> tags. However, due to the manual nature of constructing this string, the <span> elements do not have the required data attribute needed for scoped CSS in Vue components. As a result, I am unable to style these matches using scoped CSS and resort to using unscoped CSS, which is not ideal. Is there a more Vue-specific approach to achieve this styling within the scoped environment? Here is the code snippet for the highlight function:

// Source: http://stackoverflow.com/a/280805/2874789
function highlight(data, search) {
    return data.replace(
      new RegExp("(" + preg_quote(search) + ")", 'gi'),
      "<span class=match>$1</span>"
    );
}

(preg_quote is simply a function used for escaping characters)

Appreciate any assistance!

Answer №1

Generating Content Dynamically When creating DOM content with v-html, scoped styles do not affect it, but you can still apply styles using deep selectors.

There doesn't seem to be a specific VueJS method for this. Your best bet might be to either inline styling within your highlight function's output or use a global class.

function highlight(data, search) {
  return data.replace(
    new RegExp("(" + preg_quote(search) + ")", 'gi'),
     "<span class=match>$1</span>"
    );
}


<style>
  .match {
    color: yellow;
  }
</style>

or

function highlight(data, search) {
  return data.replace(
    new RegExp("(" + preg_quote(search) + ")", 'gi'),
     "<span style="{ color: yellow }">$1</span>"
    );
}

You could also explore deep selectors, although I don't have much experience with them myself.

Check out more about scoped CSS in Vue.js here.

Answer №2

Recently encountered a similar situation. A simple solution is to avoid scoping it and instead, namespace your markup and CSS classes. This prevents them from being inherited by other modules, saving you unnecessary hassle of using JavaScript for this task.

Answer №3

This is a fascinating situation.

Although using only scoped styles may not be enough, we can work around it by adding an extra <style> element with css modules (which are also scoped).

My thought process went like this:

<style scoped>
  ...
</style>

<style module>
  .match {
    color: red;
  }
</style>

Then, in your replace function, you can use:

`<span class="${this.$style.match}">...</span>`

To learn more about vue-loader's CSS module support, check out:

Answer №4

Interesting inquiry! I encountered a similar issue and managed to find a creative solution. Excited to share it with you!

Imagine your template resembles the following:

<template>
  <div class="match">
    <div v-html="<span>hello world</span>"></div>
  </div>
</template>

Simply modify this segment:

<style scoped>
.match span {
    color: yellow;
}
</style>

compiled output: `.match span[data-v-f3f3eg9] { color: yellow; }`

to

<style scoped>
.match >>> span {
    color: yellow;
}
</style>

compiled output: `.match[data-v-f3f3eg9] span { color: yellow; }`

Observe the distinction between the two outputs. You'll understand better once you compare. For more information, refer to the Vue Loader documentation.

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

customizing highcharts title within a popup window

Is there a way to dynamically set the title of a Highcharts chart from an element? Check out my code snippet below: $(function () { var chart; $('#second-chart').highcharts({ chart: { type: 'bar' }, subtitle: { ...

Unable to include query parameters in the nextjs dynamic route

I have a file called [slug].js. What I am attempting to do is add a query parameter to this dynamic route. Here's the code: await router.replace({ pathname: `${router.pathname}`, query: { coupon }, }, undefined, ...

Dynamic Population of Django Drop Down List using JavaScript

In my Django + Python website, users can request access to a database through a form that provides them with the following options: Environment: A dropdown list with two values - Development and Production. Permission: Another dropdown list with two val ...

Is there a built-in event in Jquery UI tabs for when the tabs are collapsed?

Which event in jquery ui can I utilize to detect when a panel collapse has finished on the browser? I require this information to perform calculations based on the screen layout after the collapse has occurred. If I use the select or show event callbacks, ...

How can you eliminate the first elements of two or more arrays of objects until all of their first elements match based on a specific field?

My Typescript code includes a Map object called `stat_map` defined as const stat_map: Map<string, IMonthlyStat[]> = new Map(); The interface IMonthlyStat is structured as shown below (Note that there are more fields in reality) export interface IMon ...

Is there a way for me to retrieve the data inputted into this form using JavaScript?

Having some trouble with this code. Can someone help me figure out what's going wrong? function displayData() { var userInput; userInput = document.getElementById(userInputs.firstInput); alert ("You entered: " + userInput); } <form ...

Vue 3 allows for creating multiple cards with unique contents

I received this outcome: Content duplicated but not cloned as a card element Below is the code snippet <script setup> import { ref } from 'vue'; defineProps({ project: String, }); const projectList = ref([ { img: './src/asse ...

Which specific element should the userEvent.type(...) function target in order to work effectively with MUI's DesktopDatePicker TextField component?

Is there a way for me to input text into the TextField input within the MUI datepicker using react-testing-library's user-event? I've noticed that there is a mask applied to the input. I attempted to use userEvent.type(inputEl, '1') an ...

Executing a PHP script after successful execution of another script

tag, I am encountering the following script: Two minor issues: With the button being disabled after a click, it wont allow to click again if for instance an error is returned as shown above. It should only disable it after the input has been released $fo ...

Tips for incorporating a spinner during content loading within AngularJS

When the user clicks on the "Search" button, content will load and the button label will change to "Searching" with a spinner shown while the content is loading. Once the content has loaded (Promise resolved), the button label will revert back to "Search" ...

Updating the chosen option using jQuery

Is there a way to change the currently selected option using jQuery? <select name="nameSelect" id="idSelect"> <option value="0">Text0</option> <option value="1">Text1</option> <option value="2" selected>Text ...

What is the best way to delete a property from an object in an array using Mongoose? This is crucial!

Doc - const array = [ { user: new ObjectId("627913922ae9a8cb7a368326"), name: 'Name1', balance: 0, _id: new ObjectId("627913a92ae9a8cb7a36832e") }, { user: new ObjectId("6278b20657cadb3b9a62a50e"), name: 'Name ...

Using Jquery Ajax to validate login information by submitting an HTML form

Working on a project involving jQuery Ajax, HTML forms, MySQL, and PHP. I have a database with registered users and I want to use a login form to retrieve user information from the database upon submission. However, I'm encountering an issue where the ...

The issue of not being able to go fullscreen with a YouTube iframe nested within another iframe

I have a YouTube video embedded inside another iframe, but I am facing an issue where the fullscreen feature is not working even after enabling all the required attributes. If the video isn't displaying properly in the code snippet below, you can vie ...

The reference to Vuex's this.$store is not defined

I am currently learning Vue with Vux and Vuetify. I have successfully installed it using Vue CLI. Following the documentation, I attempted to access the store but encountered an 'undefined' error for this.$storage. Here is the code snippet from ...

I require assistance in developing a mouseover image link that conceals the top image and unveils a bottom image that scrolls vertically in the exact same area as the top

I am trying to achieve a similar effect as shown on: this website I require assistance in creating a mouseover image link that hides the top image and reveals a bottom image that scrolls vertically within the same space as the top image. The long vertica ...

CSRF validation did not pass. The request has been cancelled. The failure occurred due to either a missing or incorrect CSRF token

Upon hitting the submit button in the login form, I encountered the following error message: Forbidden (403) CSRF verification failed. Request aborted. CSRF token missing or incorrect. settings.py MIDDLEWARE = [ 'django.middleware.security.Secur ...

Storing data retrieved from an asynchronous call in AngularJS to a variable

Here is the code where I am attempting to utilize promise to store data from an asynchronous call in a variable, but it's not functioning as expected. I am relatively new to promises and after some research, I learned that promises can be helpful in s ...

Which names can be used for HTML form tags in jQuery?

Recently, I encountered an issue related to jQuery form serialization which stemmed from naming a form tag "elements". The problem arose when using jQuery $(’form’).serialize(). Here is an example of the problematic code: <form> <input name=" ...

ng-repeat isn't displaying the data

I have always been comfortable using the ng-repeat in Angular, but this time I seem to be facing a problem. I am trying to populate my DOM with data from a JSON file, but for some reason, the fields are not displaying as expected. Is there something wrong ...