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

Issue with React Native TextInput failing to update state within a functional component when onChange event is triggered

When using a TextInput in a React Native functional component, I am facing an issue where the state for "name" is not updating properly when onChange occurs. To debug this issue, I have added a console log in useEffect to monitor the new state value. Howe ...

Delaying event listeners in Angular.js by using setTimeout within a factory or service

In order to delay the first iteration of the broadcast until the controller's $watchCollection is ready, I attempted using setTimeout() but it did not work as expected. Even trying with $timeout yielded the same result. What could be causing this issu ...

What is the best way to hide the drop down menu after it has been opened by clicking on the same element

My attempt to create a code that toggles a drop-down menu on every click and closes any other open menus is not working as expected. The menu doesn't close upon clicking it again. $(document).ready(function(){ "use strict"; $(".dropdown").hi ...

summing 3 numbers to a total of 100 percent

I am currently trying to calculate the percentages of different statuses based on 3 count values. Let's assume I have 3 statuses: 1) Passed 2) Failed 3) Skipped When dealing with only two cases, I was able to use a combination of the Floor and Ceil ...

changing the function of a button dynamically in vuejs depending on the data present

I have a unique scenario in my vuejs sample where I am working on dynamically changing the button based on data from the vue model. For example, if the data returned indicates "video", I want to trigger an alert method. On the other hand, if it says someth ...

Conceal Choices During Search using jQuery Select2

I'm having trouble figuring out how to make the Select2 plugin work for my specific color selection feature. My goal is to allow users to choose 5 colors from a list, including an "Other" option. When the user selects "Other", they should be able to ...

What is the best way to trigger an AJAX function every 15 seconds?

As part of my web application, I have implemented a JavaScript function that is triggered by the <body onload> event. Within this function, there is a while loop that continuously iterates until it receives the desired response from a PHP page. Unfo ...

Explore the category options in the reference document using Node.js

Category Schema const CategorySchema = mongoose.Schema( { catName: { type: String, required: true } }, { timestamps: true } ); Product Schema const ProductSchema = new mongoose.Schema( { brand: { type: String, required: true }, title: ...

Why is the lower right white space left unfilled by the color red?

I'm having issues with using named lines in grid for layout. The red section is not positioning correctly next to the footer, and I can't figure out where I went wrong. * { box-sizing: border-box; margin: 0; padding: 0; } .container { ...

"Implementing a JavaScript function to dynamically add multiple div elements to a

I am just starting to learn JavaScript. The main div with the ID "row_logic" contains two nested divs. I need help figuring out how to dynamically increment this root div in the format shown below using JavaScript. <div class="row-fluid" id="row_log ...

Position a Bootstrap 3 division within a central division for ultimate centering

I have written a code snippet that looks like this- html, body, .container-table { height: calc(100% - 50px); } /*Centering a div*/ .container-table { display: table; } .vertical-center-row { display: table-cell; vertical-align: middle; } < ...

Is it possible to use Primefaces tooltip to show at the bottom of the page

When I hover over the PrimeFaces tooltip, it displays at the bottom of the page. Here is my code and image link: <!DOCTYPE html> <h:html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com ...

Utilizing external functions within AngularJS Controller

I need to execute an external JS function that fetches data from a REST endpoint, which takes some time. The problem is that the graph is loading before the data is retrieved and inserted into it. External JS: function callEndpoint() { var sensorID = ...

The JSON.stringify function encounters difficulties when trying to format an object into

Why does JSON.stringify refuse to format objects and keep everything on a single line? <!DOCTYPE html> <html> <head> <script> var obj = { "a" : "1547645674576457645", "b" : "2790780987908790879087908790879087098", "c" ...

Exploring web pages with JavaScript events

I am currently trying to compile a list of singles that were released in the year 2018 from allmusic.com. While accessing their advanced search page and setting the parameters is simple enough, the challenge lies in extracting the information manually. Th ...

The import error states that the object 'useHistory' is not available for export from the module 'react-router-dom'

Struggling with importing useHistory from 'react-router-dom' and encountering the error message: import error: 'useHistory' is not exported from 'react-router-dom'. Despite searching for solutions like Attempted import error: ...

Display the value of a JavaScript variable in a Codeception Acceptance test

Is there a way to view the value of a vanilla JavaScript variable while running an acceptance test? In PHP, you can see the value of a variable in debug using $I->seeMyVar($var), but how can you pass the value of a JavaScript variable to a PHP variable ...

Create a full bottom shadow for a circular shape using CSS 3

Hey there, I'm having an issue with creating a separation effect for a circle. I've been using the box-shadow property like this: box-shadow: 0 1px 0 rgba(0,0,0,.2);. However, as you can see in the image, the shadow on the left and right sides is ...

A guide on identifying the data type of a value entered into an HTML table using JavaScript

Currently, I am tackling a contenteditable HTML table challenge. My goal is to enforce the insertion of only numeric values while alerting the user if they attempt to input strings or non-numeric characters. Can anyone provide guidance on how to achieve th ...

Guide on setting up a MEAN stack application to run on port 8080

I am brand new to the mean stack development environment. I'm attempting to configure my root domain name to display the app directory once I enter the command grunt, but the only way it currently works is at website.com:8080/!#/. How can I get it to ...