<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Igor Moto</title>
    <description>The latest articles on DEV Community by Igor Moto (@mprojs).</description>
    <link>https://dev.to/mprojs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F856647%2F96d06315-76a8-4d2d-a99d-b16128b14f91.jpg</url>
      <title>DEV Community: Igor Moto</title>
      <link>https://dev.to/mprojs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mprojs"/>
    <language>en</language>
    <item>
      <title>Thousands of Unique Icons: Optimizing Marker Performance in Google Maps and Mapbox GL JS</title>
      <dc:creator>Igor Moto</dc:creator>
      <pubDate>Sat, 15 Mar 2025 15:10:51 +0000</pubDate>
      <link>https://dev.to/mprojs/thousands-of-unique-icons-optimizing-marker-performance-in-google-maps-and-mapbox-gl-js-439e</link>
      <guid>https://dev.to/mprojs/thousands-of-unique-icons-optimizing-marker-performance-in-google-maps-and-mapbox-gl-js-439e</guid>
      <description>&lt;p&gt;In this article, I will share my experience optimizing the rendering of a large number of unique map markers, focusing specifically on the Google Maps JavaScript API and Mapbox GL JS. By 'unique,' I refer to markers with distinct images.&lt;/p&gt;

&lt;p&gt;Consider this scenario: we need to display points along planned routes on a map. To enhance clarity, each route is assigned a specific color, and each point is numbered from 1 to N. In my case, 20 colors were used, and the number of points per route could reach 160. This resulted in 3,200 unique color-number combinations, with the total number of markers potentially exceeding 10,000.&lt;/p&gt;

&lt;p&gt;You might wonder why not use only 20 color-coded icons and overlay the numbers as separate elements. The issue with this approach is that when markers overlap—a frequent occurrence when users zoom out—the numbers appear detached, creating a visually jarring effect. Even with individual z-index settings for each image pair, the initial rendering would be acceptable, but the display would quickly degrade after zooming.&lt;/p&gt;

&lt;p&gt;For this application, HTML markers are impractical due to their significant performance overhead with such a large quantity. Clustering is also unsuitable, as it would combine markers from different routes, undermining the goal of visually distinguishing planned routes. Furthermore, markers within a route are often connected by polylines representing the route's path.&lt;/p&gt;

&lt;p&gt;Consequently, to achieve optimal visual representation and user experience, we must render thousands of markers, many of which are unique, presenting a significant performance challenge.&lt;/p&gt;

&lt;p&gt;My initial attempt involved dynamically generating SVGs with the desired color and embedded number. Here's a simplified code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buildSitePin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;borderColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;siteNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
        &amp;lt;text
          x="14"
          y="18"
          fill="#675e58"
          text-anchor="middle"
          font-size="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;siteNumber&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;13&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;siteNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/text&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;svg&amp;gt;
        &amp;lt;g&amp;gt;
          &amp;lt;path ...real svg content here... fill="#&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseColor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" stroke="#&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;borderColor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"/&amp;gt;
          ... &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; ...
        &amp;lt;/g&amp;gt;       
      &amp;lt;/svg&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`data:image/svg+xml;base64,&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the generation process itself consumed minimal processor time, the browser's creation of images from data URLs &lt;code&gt;&amp;lt;img src="data:image....."&amp;gt;&lt;/code&gt; proved to be computationally expensive. Furthermore, the processing time increased proportionally with the number of unique images.&lt;/p&gt;

&lt;p&gt;Additionally, rendering a map with a large number of 'heavy' SVG images resulted in a noticeably unresponsive user experience.&lt;/p&gt;

&lt;p&gt;Therefore, the only viable solution was to pre-generate all icons and load them from the server. Loading thousands of individual images was clearly impractical. Instead, the images needed to be combined into an image sprite (a single image containing a collection of smaller images).&lt;/p&gt;

&lt;p&gt;For this purpose, I utilized the &lt;a href="https://www.npmjs.com/package/@jutaz/spritezero" rel="noopener noreferrer"&gt;@jutaz/spritezero&lt;/a&gt; library. First, the same function described earlier generated all the necessary SVG icons. Then, spritezero created a PNG sprite, as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flc3hu7y8mosq7t2dzaes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flc3hu7y8mosq7t2dzaes.png" alt="Image description" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also produced an object containing data specifying the precise location of each icon within the sprite, which I then transformed into the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;168&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the element's index within the pins array corresponded to the index of the required color (from our array of used colors). Using the color index, we could retrieve an object whose properties contained a number (the point's number within the route), and the value of the nested object &lt;code&gt;{"x": 168, "y": 160 }&lt;/code&gt; represented the coordinates of the top-left corner of the desired image within the sprite.&lt;/p&gt;

&lt;p&gt;I intentionally omit the complete script code for generating icons, the sprite file, and the JSON file containing the sprite's metadata from this article. The purpose is not to provide a step-by-step guide for solving a specific problem, but rather to illustrate an approach applicable to similar tasks.&lt;/p&gt;

&lt;p&gt;So, we have a sprite file and its metadata. In practice, I generated eight separate files to load only the necessary icons. The first file contained markers for all 20 colors with numbers from 1 to 20, the second from 21 to 40, and so on. Users with short routes, no more than 20 points each, would only load the first set of icons.&lt;/p&gt;

&lt;p&gt;The final and most interesting part is how to integrate the sprite with our map implementations. We’ll start with Google Maps, where the process is relatively straightforward. We create a geospatial data layer and provide a function that returns &lt;code&gt;google.maps.Data.StyleOptions&lt;/code&gt; for each point. Within this, we need to return a &lt;code&gt;google.maps.Icon&lt;/code&gt; object, whose url field can contain either the URL of a single image or that of the sprite. For sprites, we also need to specify the origin: &lt;code&gt;google.maps.Point&lt;/code&gt; field (the position of the image within the sprite).&lt;/p&gt;

&lt;p&gt;Here's an excerpt of the code where we retrieve the current point's data, determine the position of the required icon within the sprite using &lt;code&gt;getPinPosInSprite&lt;/code&gt;, and return &lt;code&gt;google.maps.Data.StyleOptions&lt;/code&gt;. As you can see, I also utilized the &lt;code&gt;pixelRatio&lt;/code&gt; field within the sprite's metadata, as I generated three versions of each sprite: one with standard pixel density (for low-resolution screens), one with double density (for Full HD), and one with quadruple density (for Retina and 4K displays). The &lt;code&gt;sitePinsSpriteService&lt;/code&gt; determined which sprite to use based on the current &lt;code&gt;window.devicePixelRatio&lt;/code&gt; value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStyle&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;colorIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;siteNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;num&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sitePinsSpriteService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;siteNumber&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posInSprite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPinPosInSprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;colorIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;siteNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;coeff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelRatio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posInSprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;coeff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;posInSprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;coeff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;scaledSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelRatio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pixelRatio&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the layer in this way, you can add and remove points by calling the &lt;code&gt;layer.add()&lt;/code&gt; and &lt;code&gt;layer.remove()&lt;/code&gt; methods, which are described in detail in the Google Maps JavaScript API documentation.&lt;/p&gt;

&lt;p&gt;Now, let's explore how to use sprites in Mapbox GL JS.&lt;/p&gt;

&lt;p&gt;First, we need to add all the required images using the &lt;code&gt;map.addImage(id, image, ...)&lt;/code&gt; method, where image can be one of the following types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="nf"&gt;addImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;HTMLImageElement&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ArrayBufferView&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Uint8ClampedArray&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ImageData&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ImageBitmap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ImageData type particularly caught my attention. According to the documentation, 'The ImageData interface represents the underlying pixel data of an area of a  element.'&lt;/p&gt;

&lt;p&gt;You can retrieve ImageData from a Canvas object using the following method:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getImageData(sx: number, sy: number, sw: number, sh: number, settings?: ImageDataSettings): ImageData;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This means that given a canvas containing the sprite image, and knowing the required position within the sprite, you can obtain any desired fragment as ImageData, which can then be passed to Mapbox using the &lt;code&gt;addImage&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;One step remains: how to convert the sprite into a Canvas. Here's an example code snippet where, after loading the sprite, I create an &lt;code&gt;OffscreenCanvas&lt;/code&gt; and append the loaded image to it. &lt;code&gt;OffscreenCanvas&lt;/code&gt; is used because we don't need to render the Canvas itself on the page; we'll use it solely for extracting fragments from the sprite. Also, note the &lt;code&gt;willReadFrequently&lt;/code&gt; option, which optimizes memory usage for frequent read operations. Here's what &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas/getContext" rel="noopener noreferrer"&gt;MDN&lt;/a&gt; says about it:&lt;br&gt;
&lt;code&gt;Boolean that indicates whether or not a lot of read-back operations are planned. This will force the use of a software (instead of hardware accelerated) 2D canvas and can save memory when calling getImageData() frequently.&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadImageFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLImageElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onerror&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;loadImageFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spriteImageUrl&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;naturalWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;naturalHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OffscreenCanvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;willReadFrequently&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following this, we can add icons to Mapbox by retrieving them from our OffscreenCanvas as follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const imageData = ctx.getImageData(x, y, width, height);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;where &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; represent the position of the desired icon within the sprite, and &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; are its dimensions. All of this information, as you recall, is available in the JSON files we generated alongside the sprite.&lt;/p&gt;

&lt;p&gt;We then pass this imageData to the map using &lt;code&gt;map.addImage(imageId, imageData)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After adding the images, we need to create a source that contains the data set in GeoJSON format. We also create a layer where we specify that the image for each feature in the GeoJSON should be the previously added icon, referenced by its &lt;code&gt;imageId&lt;/code&gt; (in my case, the imageId was a string like &lt;code&gt;${colorIndex}-${siteNumber}&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;geo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FeatureCollection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sites&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Point&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;imageId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;geojson&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;geo&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLayer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;symbol&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sourceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;   
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;icon-image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;imageId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a result, several thousand markers with unique images are rendered in less than a second. This process requires pre-loading the necessary sprite files, which, in my case, occupied 118KB for FullHD or 270KB for 4K/Retina displays per 400 icons. However, since these files rarely change, they are effectively cached by the browser.&lt;/p&gt;

&lt;p&gt;That concludes this article. Thank you for reading.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>googlemaps</category>
    </item>
    <item>
      <title>How ViewEncapsulation and ng-deep work in Angular</title>
      <dc:creator>Igor Moto</dc:creator>
      <pubDate>Mon, 02 May 2022 18:07:45 +0000</pubDate>
      <link>https://dev.to/mprojs/how-viewencapsulation-and-ng-deep-work-in-angular-5gm1</link>
      <guid>https://dev.to/mprojs/how-viewencapsulation-and-ng-deep-work-in-angular-5gm1</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcc5w9u2fft261j65h0pb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcc5w9u2fft261j65h0pb.png" alt="Keep default Angular ViewEncapsulation" width="800" height="169"&gt;&lt;/a&gt;&lt;br&gt;
Many Angular developers and layout designers who write CSS/SCSS code in Angular applications have encountered a situation where they need to apply styles to a component nested in the current one and, without fully understanding how it works, turned off style encapsulation or added ng-deep, while not taking into account some nuances, which later leads to problems. In this article, I will try to present all the details as simply and concisely as possible.&lt;br&gt;
When a component has style encapsulation enabled (it is enabled by default and should be left enabled in most cases), the styles contained in the component's style file\files will only apply to the components' elements. This is very convenient, you don't have to keep track of the uniqueness of the selectors, you don't have to use BEM or come up with long class names and keep them unique, although you can still do that if you want. During the creation of each component, Angular itself will add a unique attribute to all elements inside the component, for example, &lt;code&gt;_ngcontent-ool-c142&lt;/code&gt; and replace your &lt;code&gt;.my-class&lt;/code&gt; selector with &lt;code&gt;.my-class[_ngcontent-ool-c142]&lt;/code&gt; (this is in the case of &lt;code&gt;ViewEncapsulation.Emulated&lt;/code&gt; , which is enabled by default, if you specify &lt;code&gt;ViewEncapsulation.ShadowDom&lt;/code&gt; the behavior is different but the result is the same).&lt;/p&gt;

&lt;p&gt;Now let's imagine that we have a component named &lt;code&gt;ComponentA&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"checkbox-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;mat-checkbox&amp;gt;&lt;/span&gt;Check me&lt;span class="nt"&gt;&amp;lt;/mat-checkbox&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that has a mat-checkbox from Angular material nested inside it (this can be your own component, not necessarily components from libraries).&lt;/p&gt;

&lt;p&gt;Inside mat-checkbox there is a label that we want to add a border to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;mat-checkbox&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we write in the component's style file,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;mat-checkbox&lt;/span&gt; &lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#aabbcc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then after applying &lt;code&gt;ViewEncapsulation.Emulated&lt;/code&gt; the selector will be something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;mat-checkbox&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;_ngcontent-uiq-c101&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;   &lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;_ngcontent-uiq-c101&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#aabbcc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;i.e. the border will be applied to the label with the &lt;code&gt;_ngcontent-uiq-c101&lt;/code&gt; attribute, but all child elements inside the &lt;code&gt;mat-checkbox&lt;/code&gt; will have a different attribute since the label is inside another component and it will either have an attribute with a different ID (id of &lt;code&gt;mat-checkbox&lt;/code&gt; component), or it will not exist at all if the component, in turn, has encapsulation disabled (in our case, there will be no attribute at all, because mat-checkbox, like other components from Angular Material has &lt;code&gt;ViewEncapsulation.None&lt;/code&gt;).&lt;br&gt;
    Thus, styles restricted by the &lt;code&gt;ComponentA&lt;/code&gt; component attribute only apply to elements directly inside that component. If the component contains another component, then these styles no longer apply to its elements. &lt;br&gt;
If you're wondering exactly how Angular's Emulated encapsulation works, you can find a lot of detailed articles on the subject, but here I'll give a very brief description so as not to bloat the article. If the component has encapsulation, then the &lt;code&gt;_nghost-ID&lt;/code&gt; attribute will be added to the component itself, and the &lt;code&gt;_ngcontent-ID&lt;/code&gt; attribute will be added to each nested element, and &lt;code&gt;[_ngcontent-ID]&lt;/code&gt; will be added to all styles in this component. This way all styles will be applied ONLY to the elements inside that component.&lt;/p&gt;

&lt;p&gt;What if we need to apply styles to the elements inside the nested component (in our example, to the label inside the mat-checkbox) &lt;/p&gt;

&lt;p&gt;In order to apply styles, we have three options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;disable style encapsulation in ComponentA &lt;/li&gt;
&lt;li&gt;use ng-deep &lt;/li&gt;
&lt;li&gt;place css code in global styles (those in styles.(s)css or in other files specified in the styles section in angular.json) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a closer look at them&lt;/p&gt;
&lt;h2&gt;
  
  
  ViewEncapsulation.None
&lt;/h2&gt;

&lt;p&gt;In this case, all styles inside the component will become "global", and this will happen only after the component is created, i.e. after the user has visited the section of the application where this component is used, which makes it very difficult to identify this problem. Let's turn off style encapsulation on our component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-component-a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./component-a.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./component-a.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;encapsulation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ViewEncapsulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;None&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;remember that in the style file we have this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;mat-checkbox&lt;/span&gt; &lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#aabbcc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;until the user has opened the page where component A is used, all other mat-checkboxes in the application look borderless, but after component A has rendered, the css code above will be dynamically added to the  section in the DOM tree and after then all mat-checkboxes will use these styles. &amp;lt;br&amp;gt;
In order to prevent this apparently undesirable effect, we can limit the scope of styles by applying a more specific selector. For example, let&amp;amp;#39;s add the &amp;amp;quot;checkbox-container&amp;amp;quot; class to the mat-checkbox&amp;amp;#39;s parent element,&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight html"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;amp;lt;div&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;class=&amp;lt;/span&amp;gt;&amp;lt;span class="s"&amp;gt;"checkbox-container"&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;span class="nt"&amp;gt;&amp;amp;lt;mat-checkbox&amp;amp;gt;&amp;lt;/span&amp;gt;Check me&amp;lt;span class="nt"&amp;gt;&amp;amp;lt;/mat-checkbox&amp;amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;span class="nt"&amp;gt;&amp;amp;lt;/div&amp;amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;and fix the selector to this&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight css"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nc"&amp;gt;.checkbox-container&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;mat-checkbox&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;label&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
  &amp;lt;span class="nl"&amp;gt;border&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;1px&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;solid&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;#aabbcc&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;now only checkboxes located inside an element with the checkbox-container class will get the border. But instead of adding a class with a unique name and making sure they&amp;amp;#39;re not repeatable, it&amp;amp;#39;s much easier to use a component selector, because it will be unique&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight css"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nt"&amp;gt;app-component-a&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;mat-checkbox&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;label&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
  &amp;lt;span class="nl"&amp;gt;border&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;1px&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;solid&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;#aabbcc&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Conclusion: if you turn off encapsulation, don&amp;amp;#39;t forget to add the component selector to ALL styles inside the component, in case of SCSS\SASS, just wrap all code in:&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight css"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nt"&amp;gt;app-component-a&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
  &amp;lt;span class="err"&amp;gt;...&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;h2&amp;gt;
  &amp;lt;a name="pseudoclass-ngdeep" href="#pseudoclass-ngdeep" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  Pseudo-class ng-deep
&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Now let&amp;amp;#39;s turn encapsulation back on by removing encapsulation: &amp;lt;code&amp;gt;ViewEncapsulation.None&amp;lt;/code&amp;gt; from the &amp;lt;code&amp;gt;@Component&amp;lt;/code&amp;gt; decorator. And add the &amp;lt;code&amp;gt;::ng-deep&amp;lt;/code&amp;gt; selector to the css&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight css"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nd"&amp;gt;::ng-deep&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;mat-checkbox&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;label&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
  &amp;lt;span class="nl"&amp;gt;border&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;1px&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;solid&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;#aabbcc&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;code&amp;gt;ng-deep&amp;lt;/code&amp;gt; will force the framework to generate styles without adding attributes to them, as a result, this code will be added to the DOM:&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight css"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nt"&amp;gt;mat-checkbox&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;label&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span class="nl"&amp;gt;border&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;span class="m"&amp;gt;1px&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;solid&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;#aabbcc&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;which will affect all mat-checkbox applications, just like if we added it to global styles or turned off encapsulation as we did earlier. To avoid this behavior, we can again restrict the scope to the component selector&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight css"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nd"&amp;gt;::ng-deep&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;app-component-a&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;mat-checkbox&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;label&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
  &amp;lt;span class="nl"&amp;gt;border&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;1px&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;solid&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;#aabbcc&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;or do it even simpler and use the &amp;lt;code&amp;gt;:host&amp;lt;/code&amp;gt; pseudo-class&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight css"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nd"&amp;gt;:host&amp;lt;/span&amp;gt; &amp;lt;span class="nd"&amp;gt;::ng-deep&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;mat-checkbox&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;label&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
  &amp;lt;span class="nl"&amp;gt;border&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;1px&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;solid&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;#aabbcc&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;which is much more convenient and reliable (imagine if you renamed the component selector and forgot to change it in the css code). &amp;lt;br&amp;gt;
How does it work? Very simple - Angular will generate in this case the following styles&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight css"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="o"&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;_nghost-qud-c101&amp;lt;/span&amp;gt;&amp;lt;span class="o"&amp;gt;]&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;mat-checkbox&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;label&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;&amp;lt;span class="nl"&amp;gt;border&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;span class="m"&amp;gt;1px&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;solid&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;#aabbcc&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;where &amp;lt;code&amp;gt;_nghost-qud-c101&amp;lt;/code&amp;gt; is the attribute added to our &amp;lt;code&amp;gt;ComponentA&amp;lt;/code&amp;gt;, i.e. the border will apply to all labels inside any mat-checkbox lying inside an element with the &amp;lt;code&amp;gt;_nghost-qud-c101&amp;lt;/code&amp;gt; attribute, which ONLY &amp;lt;code&amp;gt;ComponentA&amp;lt;/code&amp;gt; has.&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight html"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;amp;lt;app-component-a&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;_ngcontent-qud-c102&amp;lt;/span&amp;gt; &amp;lt;span class="na"&amp;gt;_nghost-qud-c101&amp;lt;/span&amp;gt;&amp;lt;span class="nt"&amp;gt;&amp;amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Conclusion: if using ::ng-deep ALWAYS add :host or create a mixin and use it everywhere&amp;lt;/strong&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight css"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="k"&amp;gt;@mixin&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;ng-deep&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
  &amp;lt;span class="nd"&amp;gt;:host&amp;lt;/span&amp;gt; &amp;lt;span class="nd"&amp;gt;::ng-deep&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
    &amp;lt;span class="err"&amp;gt;&lt;a class="mentioned-user" href="https://dev.to/content"&gt;@content&lt;/a&gt;;&amp;lt;/span&amp;gt;
  &amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;

&amp;lt;span class="k"&amp;gt;&lt;a class="mentioned-user" href="https://dev.to/include"&gt;@include&lt;/a&gt;&amp;lt;/span&amp;gt; &amp;lt;span class="n"&amp;gt;ng-deep&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
  &amp;lt;span class="nt"&amp;gt;mat-checkbox&amp;lt;/span&amp;gt; &amp;lt;span class="nt"&amp;gt;label&amp;lt;/span&amp;gt; &amp;lt;span class="p"&amp;gt;{&amp;lt;/span&amp;gt;
    &amp;lt;span class="nl"&amp;gt;border&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;:&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;1px&amp;lt;/span&amp;gt; &amp;lt;span class="nb"&amp;gt;solid&amp;lt;/span&amp;gt; &amp;lt;span class="m"&amp;gt;#aabbcc&amp;lt;/span&amp;gt;&amp;lt;span class="p"&amp;gt;;&amp;lt;/span&amp;gt;
  &amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;span class="p"&amp;gt;}&amp;lt;/span&amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Many developers are confused by the fact that &amp;lt;code&amp;gt;ng-deep&amp;lt;/code&amp;gt; has been marked as deprecated for a long time. The Angular team had plans to deprecate this pseudo-class, but that decision was later shelved indefinitely, at least until new alternatives come along. If we compare &amp;lt;code&amp;gt;ng-deep&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ViewEncapsulation.None&amp;lt;/code&amp;gt;, then in the first case, we at least turn off encapsulation not for all component styles, but only for those that we need. Even if you have a component where all the styles are for child components, ng-deep seems to be more advantageous because you can later add styles for the component&amp;amp;#39;s own elements, in which case you just write them above/below the code nested in &amp;lt;code&amp;gt;:host ::ng-deep {}&amp;lt;/code&amp;gt; and they will work as usual, but with encapsulation disabled, you no longer have this option.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Finally, I want to add a few words about how to “style” components from libraries. If you need to change the default view for, say, all mat-selects in your application, it&amp;amp;#39;s often best to do so in global styles. Sometimes, some developers prefer to put these styles in a separate SCSS file and import it wherever needed, but in this case, when building the project, these styles are duplicated in each chank (compiled js file for a lazy or shared module / group of modules) , where at least one of the components included in this chank uses this style file, which can significantly increase the total size of the bundle. Therefore, this practice should be avoided.&amp;lt;/p&amp;gt;
&lt;/p&gt;

</description>
      <category>angular</category>
      <category>viewencapsulation</category>
      <category>css</category>
    </item>
  </channel>
</rss>
