Step-by-step guide on incorporating Google Fonts and Material Icons into Vue 3 custom web components

While developing custom web components with Vue 3 for use in various web applications, I encountered an issue related to importing fonts and Google material icons due to the shadow-root. Currently, my workaround involves adding the stylesheet link tag to the application header during the registration of the web components. Although this method works, I am concerned that it undermines the encapsulation concept of web components and could potentially impact the styles of the application utilizing my custom web components.

Below is my current implementation:

import { defineCustomElement as VueDefineCustomElement, h, getCurrentInstance } from 'vue';

export function register() {
  // Icons
  loadStylesheet(
    'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d79085969397e5e7f9f9e3ef">[email protected]</a>,100..700,0..1,-50..200'
  );
  // Fonts
  loadStylesheet('https://fonts.googleapis.com/css2?family=Lato:wght@400;500;600;700&display=swap');

  // Components
  customElements.define('comp', defineCustomElement(comp1));

  ...
}

export const defineCustomElement = (component) => {
  ...

  return VueDefineCustomElement({
    setup() {
      ... // Data injection
      return () => h(component);
    },
  });
};

// Function to add the stylesheets to the application's head tag
function loadStylesheet(href) {
  let existingNode = null; 
  for (let i = 0; i < document.styleSheets.length; i++) {
    if (document.styleSheets[i].href && document.styleSheets[i].href.indexOf(href) > -1) {
      existingNode = document.styleSheets[i].ownerNode;
      break;
    }
  }
  if (existingNode) {
    return;
  }

  let linkTag = document.createElement('link');
  linkTag.rel = 'stylesheet';
  linkTag.href = href;
  document.getElementsByTagName('head')[0].appendChild(linkTag);
}

In the root component, I have done the following:

@import url('../index.css');
@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="93d4c1d2d7d3a1a3bdbda7ab">[email protected]</a>,100..700,0..1,-50..200');
:host {
  font-family: Lato, Arial, Helvetica, sans-serif;
}

I have considered downloading the font and using SVGs instead of icons, but I'm worried that this approach might increase the bundle size.

Answer №1

If you want to incorporate icons into your website, simply sign up for Font Awesome and obtain your personalized kit code.

After adding the code to the HTML header section, you can easily browse their collection of icons and insert them as needed.

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

retrieving embedded content from an iframe on Internet Explorer version 7

Need help with iframe content retrieval $('.theiframe').load(function(){ var content = $(this.contentDocument).find('pre').html(); } I'm facing an issue where the iframe content is retrieved properly in FF, Chrome, and IE 8,9 ...

Please input a number that falls within a specified range

I need help with two text inputs that are connected v-model to a ref object. I also have two other refs, minimum (100) and maximum(1000). My goal is to allow users to input values within the range of the minimum and maximum values provided. If the value en ...

How do I view a wildcard in my ID selector using jQuery?

When I want to initially hide various content scattered around the page, I usually use the following jQuery code: $('#objective_details, #time_estimate_details, #team_members_details, #resources_details').hide(); Is there a method to utilize a ...

"Executing a query on Angular Firestore using the where clause fetches all documents from the

I am encountering a perplexing issue with my angular app that is connected to Firestore. Despite following the documentation closely, when I query for documents in a collection based on a specific condition, the array returned contains every single documen ...

Reacting to URL Changes but Failing to Load the Requested Page

Welcome to my App Component import React, { useEffect } from 'react'; import './App.css'; import Navbar from './components/layout/Navbar'; import Landing from './components/layout/Landing'; import { BrowserRouter as ...

Difficulty accessing class functions from the test application in Node.js NPM and Typescript

I created an NPM package to easily reuse a class. The package installs correctly and I can load the class, but unfortunately I am unable to access functions within the class. My project is built using TypeScript which compiles into a JavaScript class: For ...

Unable to log out when the button is clicked

I am having trouble figuring out why I can't log out when clicking the button. I have a logout button in my header (navigation). My experience with React is limited. Within my project folder, I have a Store directory which contains an Auth-context f ...

Tips for sending multiple values in a data object using jQuery AJAX

I am currently working on a form that contains two input fields, with the possibility of more being added later. The first input is a text field and the second is a checkbox. I want to be able to send these inputs using $.ajax. To accomplish this, I have ...

Looking for assistance in setting up a personalized slideshow to automatically play on its

Recently, I have taken responsibility for a project that was initiated by someone else. The website contains a customized slideshow on its homepage. To meet the client's requirements, I have already made some alterations to the appearance and feel of ...

Issue with Context Menu Not Triggering on Dynamically Added Elements in JQuery

Check out the JSFiddle Demo Within my email sidebar, I implemented a custom right-click feature that allows users to add new sub-folders. The code snippet below demonstrates how this functionality works: if ($(this).hasClass('NewSubFolder')) { ...

What is the best way to access a video stored in a local file on the initial page and then watch it on the subsequent

I recently encountered a scenario where I needed to select a video on one page and have it automatically play on another page without any redirection. The initial page displays a list of videos for selection, like this: FirstPage Once a video is chosen on ...

How do I navigate to a different page in Vue.js HTML based on user selection?

Here is my first attempt at writing HTML code: <div class="col-md-4" > <div class="form-group label-floating"> <label class="control-label">Select No</label> <select class="form-control" v-model="or" required=""> ...

Tips for updating the color, background, and height of the particle background using react-tsparticles

Is it possible to customize color and background in react-tsparticles? Below is an example of a particle configuration file named particle-config.js const particlesConfig = { background: { color: { value: "#232741", }, posi ...

Having trouble with setting up local notifications in React Native's scheduling feature?

I have integrated the react-native-push-notifications npm library into my application to enable notifications. However, I am facing an issue while trying to schedule notifications using PushNotification.localNotificationSchedule. The code snippet for this ...

Creating Eye-Catching Images by Incorporating Image Overlays Using Just One Image

I'm facing a bit of a challenge here. I need to figure out how to overlay an image onto another image using just a single image tag. Specifically, I want to add a resize icon to the bottom right corner of an image to let users know they can resize it ...

Update data in PHP dynamically without reloading the page

It would be great if they are doing well! I have encountered a minor issue - everything seems to work perfectly, but it doesn't quite meet my requirements. I am referring to this particular function: <script> var previous = null; var current = ...

How can I make sure certain properties in the Vuex store don't retain their state after a redirect during server-side rendering (SSR)?

Our approach involves server-side rendering with the use of preserveState to persist all vuex modules' state when navigating between pages. However, we have a specific store where we need to exclude certain properties from persistence. Is there a sol ...

The content is stationary as the side menu slides open and closed

I have successfully implemented a sliding side menu in my angularjs+bootstrap3 app using CSS. However, I am facing an issue where the content on the right side does not follow the menu when it slides out of view. Here is the desired effect that I am aimin ...

Replace the pixel measurements with percentage values

I have a vision for creating a dynamic full-width slider using a flex-wrapper and multiple child sections. Each section spans the width of the viewport and is aligned in a row. The goal is to move the flex-wrapper by 100% margin-left every time a button ...

Error with constructor argument in NestJS validator

I've been attempting to implement the nest validator following the example in the 'pipes' document (https://docs.nestjs.com/pipes) under the "Object schema validation" section. I'm specifically working with the Joi example, which is fun ...