{"id":11703,"date":"2022-06-14T20:18:32","date_gmt":"2022-06-14T20:18:32","guid":{"rendered":"https:\/\/www.htmlgoodies.com\/?p=11703"},"modified":"2022-06-14T20:18:32","modified_gmt":"2022-06-14T20:18:32","slug":"custom-less-styles-angular","status":"publish","type":"post","link":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/","title":{"rendered":"Importing Custom Less Styles at Run-time in Angular"},"content":{"rendered":"

The organization where I work employs a common library for individual clients’ styles. These override the defaults as part of project builds. More recently, things have become slightly more complicated as Angular components are also being sold as individual widgets. These do not follow the same build process as applications; rather than compile Less variables in advance, these receive all colors via @Input<\/strong> parameters. As such, Less files must be imported by the widget at run-time, compiled, and converted to JavaScript Objects whose values may be utilized to set application variables. As the principal investigator into the architectural design of that process, I am now in a position to share my findings with you, the reader. This tutorial will follow a similar path as did the Setting CSS Values from Less Variables in Angular<\/a> article, but this time, we’ll be fetching a Less stylesheet to go along with the Less variables, allowing us to entirely separate theme styles from our widget component.<\/p>\n

Introducing the Less Service<\/h2>\n

As we do more processing of Less files, it only makes sense to encapsulate all of this functionality within a service. Let’s call it less-service.ts<\/strong> and place it in a services folder:<\/p>\n

\"Lss<\/p>\n

 <\/p>\n

All of the code that we will be writing here today, with the exception of the very last code snippet, will go into our service.<\/p>\n

Reading Multiple Files Using the Angular HttpClient<\/h2>\n

In the Setting CSS Values from Less Variables in Angular<\/a> tutorial, we read the contents of the variables.less file<\/strong>, located in the src\/assets<\/strong> folder of our project. This time around, we will also be accessing styles from the common-styles.less<\/strong> file. We can not compile the styles without the variables, so we should use the RxJS forkJoin()<\/strong> function to retrieve the contents of both files together. ForkJoin<\/strong> is ideal for working with observables that only emit one value, or when we only require the last value of each before completion. As it happens, the HttpClient’s get()<\/strong> method returns an Observable that can be passed directly to forkJoin()<\/strong>:<\/p>\n

import { HttpClient } from \"@angular\/common\/http\";\r\nimport { Injectable } from \"@angular\/core\";\r\nimport { forkJoin, ReplaySubject } from \"rxjs\";\r\n\r\n@Injectable()\r\nexport class LessService {\r\n  constructor(http: HttpClient) {\r\n    forkJoin([\r\n      http.get('.\/assets\/variables.less', {responseType: 'text'}),\r\n      http.get('.\/assets\/common-styles.less', {responseType: 'text'})\r\n    ])\r\n      .subscribe(\r\n        data => {\r\n           \/\/ Process files here... \r\n        },\r\n        err => {\r\n          console.log(err);\r\n        });\r\n  }\r\n}\r\n<\/pre>\n

To invoke the LessService<\/strong> constructor, all we need to do is inject our service into our AppComponent<\/strong> as a constructor argument, and Angular will take care of the rest!<\/p>\n

import { LessService } from '.\/services\/less-service';\r\n\r\nexport class AppComponent {\r\n  constructor(lessService: LessService) {\r\n  }\r\n}\r\n<\/pre>\n

Read:<\/strong> HTML, CSS, and JavaScript Tools and Libraries<\/a><\/p>\n

How to Convert Less Variables to a JavaScript Object<\/h2>\n

To convert our variables to JavaScript, we will use the less-vars-to-js<\/a> library, just as we did last time. The only difference is that the data object now consists of a two element array \u2013 one for each returned Observable. Hence, the contents of the variables.less<\/strong> file are contained in element zero, i.e., data[0]<\/strong>:<\/p>\n

import less from 'less';\r\nimport lessToJs from 'less-vars-to-js';\r\n\r\n  \/\/ ...\r\n  .subscribe(\r\n    data => {\r\n    let vars: Object;\r\n    try {\r\n      vars = lessToJs(data[0]);\r\n    } catch(err) {\r\n      console.log(err);\r\n      return;\r\n    } \r\n<\/pre>\n

Appending Compiles Less Styles as a New StyleSheet<\/h3>\n

To compile the Less files, we’ll again be using the official, stable version of the Less npm<\/strong> JS library. Then, we will activate the compiled CSS rules by appending them as a new stylesheet in the document head. The trick to making that work is to assign the sheet’s innerText <\/strong>to the cssObject’s css<\/strong> property, which holds the compiled rules as a string:<\/p>\n

const options = { modifyVars: vars };\r\nless.render(data[1], options)\r\n  .then((cssObject) => {\r\n    const sheet = document.createElement('style');\r\n    sheet.innerText = cssObject.css;\r\n    sheet.title = 'common-styles';\r\n    const head = document.getElementsByTagName('head')[0];\r\n    head.appendChild(sheet);\r\n    \/\/ Set default colors...\r\n  })\r\n  .catch((reason) => console.error(reason));\r\n<\/pre>\n

At this point, the new styles (shown below) should be immediately picked up by the browser and reflected in the application.<\/p>\n

.background {  \r\n  background-color: #52acf0;\r\n}\r\n.hover-background {  \r\n  background-color: #b0d9f8;\r\n}\r\n.focus-border-background {\r\n  background-color: gray;\r\n}\r\n<\/pre>\n

That being said, the default theme colors will not trickle down to the FeedComponent<\/strong> Widget<\/strong> because, as mentioned in the web development tutorial introduction, those are set via @Input<\/strong> parameters. As such, they will not be picked up unless the AppComponent<\/strong> overrides its own default values with those of the variables.less<\/strong> file:<\/p>\n

\"Working<\/p>\n

 <\/p>\n

We can see in the above image that the backgroundColorInput <\/strong>value of ‘cyan’<\/strong> is currently being passed to the FeedComponent<\/strong>, whereas the @BackgroundColor<\/strong> defined in variables.less is “rgb(82, 172, 240)”<\/strong>. Should the owners of the client application that hosts the FeedComponent<\/strong> widget choose to go with the default theme colors, as defined in the variables.less<\/strong> file, they can do so by reading them in from the compiled CSS rules. The LessService<\/strong> can facilitate that by mapping Less variables to their values and making the Map<\/strong> available to subscribing components:<\/p>\n

private _variablesMap$ = new ReplaySubject<Map<string, string>>(1);\r\n\r\npublic get variablesMap$() {\r\n  return this._variablesMap$.asObservable();\r\n}\r\n<\/pre>\n

To access the generated color values, we can repeat the same process as above using some dummy rules where each rule corresponds to a color variable, like so:<\/p>\n

BackgroundColor { color: \"#52acf0\"; } \r\nFocusBorderColor { color: \"gray\"; } \r\nHoverColor { color: \"#b0d9f8\"; } \r\n<\/pre>\n

Here is the code that wraps each custom variable and its associated value inside a dummy rule:<\/p>\n

let dummyCssRules = \r\n  Object.keys(vars) \/\/ Remove the '@' for the map key\r\n    .map(key => key.substring(1) + ' { color: ' + key + '; }\\n')\r\n    .join('');\r\n<\/pre>\n

We can now render the rules into CSS using the less JS library and convert the CSS rules to a JS Object. For that step, we will use the css-to-js<\/a> library’s convert()<\/strong> function, so that we can access the rule names and their color attribute. One way to create the variablesMap<\/strong> from the JS Object is to run its keys through the Array’s map()<\/strong> method as there is a Map constructor for an array of key\/value pairs. Finally, we can broadcast the variablesMap<\/strong> to subscribers and call complete()<\/strong> to let them know that there will not be any more broadcasts:<\/p>\n

import less from 'less';\r\n\r\n\/\/ ... \r\nless.render(dummyCssRules, options)\r\n  .then(cssObject => {\r\n    const compiledCssObject: Object = convert(cssObject.css);   \r\n    const variablesMap: Map<string, string> \r\n\t  = new Map(\r\n\t    Object.entries(compiledCssObject)\r\n\t\t  .map(([key, rule]: [string, string]) => [key, rule['color']])\r\n\t    );\r\n    \/\/ Broadcast the variablesMap to subscribers\r\n    this._variablesMap$.next(variablesMap);\r\n    this._variablesMap$.complete();\r\n  })\r\n  .catch((reason) => console.error(reason));\r\n<\/pre>\n

Read:<\/strong> Project Management Tools for Web Developers<\/a><\/p>\n

Setting the FeedComponent Widget Colors with Less<\/h2>\n

In the AppComponent’s<\/strong> constructor, we can access the lessService<\/i><\/strong> parameter and subscribe to its public variablesMap$<\/i><\/strong> getter. Each color has the same name as in the variables.less<\/strong> file, but without the ‘@’<\/strong> symbol:<\/p>\n

constructor(lessService: LessService) {\r\n  lessService.variablesMap$\r\n    .subscribe(variablesMap => {\r\n      this.setColors(\r\n        variablesMap.get('BackgroundColor'), \r\n        variablesMap.get('HoverColor'), \r\n        variablesMap.get('FocusBorderColor')\r\n      );\r\n    });\r\n}\r\n<\/pre>\n

Now we can see the variables.less<\/strong> colors reflected in the demo app<\/a>:<\/p>\n

\"Feed<\/p>\n

 <\/p>\n

Final Thoughts on Importing Custom Less Styles at Run-time in Angular<\/h2>\n

In this web development tutorial, we learned how to import Less files at run-time, in order to set CSS rules and individual color attributes in Angular applications. An alternative approach would be to employ a webpack script that does all of this during project builds. The advantage of importing styles from the application is that it offers a lot more flexibility at run-time. The bottom line is that you’ve got choices, and that’s always a good thing.<\/p>\n

Read more JavaScript and web development tutorials<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"

The organization where I work employs a common library for individual clients’ styles. These override the defaults as part of project builds. More recently, things have become slightly more complicated as Angular components are also being sold as individual widgets. These do not follow the same build process as applications; rather than compile Less variables […]<\/p>\n","protected":false},"author":90,"featured_media":11707,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[30588],"tags":[8817,4810,3385,33896,31136],"b2b_audience":[37],"b2b_industry":[65],"b2b_product":[69,70,71,76,131,68,118,81,82,133,83,84,107,86,30818,93,94,99,114,115,116,85,522,117,80,128,98,135],"acf":[],"yoast_head":"\nImporting Custom Less Styles at Run-time in Angular | HTMLGoodies.com<\/title>\n<meta name=\"description\" content=\"Learn how to work with Less variables, JavaScript, and CSS in this web development tutorial, which features code examples.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Importing Custom Less Styles at Run-time in Angular | HTMLGoodies.com\" \/>\n<meta property=\"og:description\" content=\"Learn how to work with Less variables, JavaScript, and CSS in this web development tutorial, which features code examples.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/\" \/>\n<meta property=\"og:site_name\" content=\"HTML Goodies\" \/>\n<meta property=\"article:published_time\" content=\"2022-06-14T20:18:32+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2022\/06\/Less-variables-web-development-tutorial-scaled.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1882\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@htmlgoodies\" \/>\n<meta name=\"twitter:site\" content=\"@htmlgoodies\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Rob Gravelle\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#organization\",\"name\":\"HTML Goodies\",\"url\":\"https:\/\/www.htmlgoodies.com\/\",\"sameAs\":[\"https:\/\/twitter.com\/htmlgoodies\"],\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/03\/HTMLg_weblogo_MobileLogo.png\",\"contentUrl\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/03\/HTMLg_weblogo_MobileLogo.png\",\"width\":584,\"height\":136,\"caption\":\"HTML Goodies\"},\"image\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/logo\/image\/\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#website\",\"url\":\"https:\/\/www.htmlgoodies.com\/\",\"name\":\"HTML Goodies\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.htmlgoodies.com\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#primaryimage\",\"url\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2022\/06\/Less-variables-web-development-tutorial-scaled.jpeg\",\"contentUrl\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2022\/06\/Less-variables-web-development-tutorial-scaled.jpeg\",\"width\":2560,\"height\":1882,\"caption\":\"How to Work with Less Variables\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#webpage\",\"url\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/\",\"name\":\"Importing Custom Less Styles at Run-time in Angular | HTMLGoodies.com\",\"isPartOf\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#primaryimage\"},\"datePublished\":\"2022-06-14T20:18:32+00:00\",\"dateModified\":\"2022-06-14T20:18:32+00:00\",\"description\":\"Learn how to work with Less variables, JavaScript, and CSS in this web development tutorial, which features code examples.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.htmlgoodies.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Importing Custom Less Styles at Run-time in Angular\"}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#webpage\"},\"author\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/d340101131281902e682ad0190b7ac75\"},\"headline\":\"Importing Custom Less Styles at Run-time in Angular\",\"datePublished\":\"2022-06-14T20:18:32+00:00\",\"dateModified\":\"2022-06-14T20:18:32+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#webpage\"},\"wordCount\":988,\"publisher\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2022\/06\/Less-variables-web-development-tutorial-scaled.jpeg\",\"keywords\":[\"Angular\",\"CSS\",\"JavaScript\",\"Observables\",\"variables\"],\"articleSection\":[\"CSS\"],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/d340101131281902e682ad0190b7ac75\",\"name\":\"Rob Gravelle\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/05\/rob-gravelle-150x150.jpg\",\"contentUrl\":\"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/05\/rob-gravelle-150x150.jpg\",\"caption\":\"Rob Gravelle\"},\"description\":\"Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.\",\"url\":\"https:\/\/www.htmlgoodies.com\/author\/rob-gravelle\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Importing Custom Less Styles at Run-time in Angular | HTMLGoodies.com","description":"Learn how to work with Less variables, JavaScript, and CSS in this web development tutorial, which features code examples.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/","og_locale":"en_US","og_type":"article","og_title":"Importing Custom Less Styles at Run-time in Angular | HTMLGoodies.com","og_description":"Learn how to work with Less variables, JavaScript, and CSS in this web development tutorial, which features code examples.","og_url":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/","og_site_name":"HTML Goodies","article_published_time":"2022-06-14T20:18:32+00:00","og_image":[{"width":2560,"height":1882,"url":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2022\/06\/Less-variables-web-development-tutorial-scaled.jpeg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_creator":"@htmlgoodies","twitter_site":"@htmlgoodies","twitter_misc":{"Written by":"Rob Gravelle","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Organization","@id":"https:\/\/www.htmlgoodies.com\/#organization","name":"HTML Goodies","url":"https:\/\/www.htmlgoodies.com\/","sameAs":["https:\/\/twitter.com\/htmlgoodies"],"logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/03\/HTMLg_weblogo_MobileLogo.png","contentUrl":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/03\/HTMLg_weblogo_MobileLogo.png","width":584,"height":136,"caption":"HTML Goodies"},"image":{"@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/logo\/image\/"}},{"@type":"WebSite","@id":"https:\/\/www.htmlgoodies.com\/#website","url":"https:\/\/www.htmlgoodies.com\/","name":"HTML Goodies","description":"","publisher":{"@id":"https:\/\/www.htmlgoodies.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.htmlgoodies.com\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#primaryimage","url":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2022\/06\/Less-variables-web-development-tutorial-scaled.jpeg","contentUrl":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2022\/06\/Less-variables-web-development-tutorial-scaled.jpeg","width":2560,"height":1882,"caption":"How to Work with Less Variables"},{"@type":"WebPage","@id":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#webpage","url":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/","name":"Importing Custom Less Styles at Run-time in Angular | HTMLGoodies.com","isPartOf":{"@id":"https:\/\/www.htmlgoodies.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#primaryimage"},"datePublished":"2022-06-14T20:18:32+00:00","dateModified":"2022-06-14T20:18:32+00:00","description":"Learn how to work with Less variables, JavaScript, and CSS in this web development tutorial, which features code examples.","breadcrumb":{"@id":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.htmlgoodies.com\/"},{"@type":"ListItem","position":2,"name":"Importing Custom Less Styles at Run-time in Angular"}]},{"@type":"Article","@id":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#article","isPartOf":{"@id":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#webpage"},"author":{"@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/d340101131281902e682ad0190b7ac75"},"headline":"Importing Custom Less Styles at Run-time in Angular","datePublished":"2022-06-14T20:18:32+00:00","dateModified":"2022-06-14T20:18:32+00:00","mainEntityOfPage":{"@id":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#webpage"},"wordCount":988,"publisher":{"@id":"https:\/\/www.htmlgoodies.com\/#organization"},"image":{"@id":"https:\/\/www.htmlgoodies.com\/css\/custom-less-styles-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2022\/06\/Less-variables-web-development-tutorial-scaled.jpeg","keywords":["Angular","CSS","JavaScript","Observables","variables"],"articleSection":["CSS"],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/d340101131281902e682ad0190b7ac75","name":"Rob Gravelle","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.htmlgoodies.com\/#\/schema\/person\/image\/","url":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/05\/rob-gravelle-150x150.jpg","contentUrl":"https:\/\/www.htmlgoodies.com\/wp-content\/uploads\/2021\/05\/rob-gravelle-150x150.jpg","caption":"Rob Gravelle"},"description":"Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.","url":"https:\/\/www.htmlgoodies.com\/author\/rob-gravelle\/"}]}},"_links":{"self":[{"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/posts\/11703"}],"collection":[{"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/users\/90"}],"replies":[{"embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/comments?post=11703"}],"version-history":[{"count":0,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/posts\/11703\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/media\/11707"}],"wp:attachment":[{"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/media?parent=11703"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/categories?post=11703"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/tags?post=11703"},{"taxonomy":"b2b_audience","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/b2b_audience?post=11703"},{"taxonomy":"b2b_industry","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/b2b_industry?post=11703"},{"taxonomy":"b2b_product","embeddable":true,"href":"https:\/\/www.htmlgoodies.com\/wp-json\/wp\/v2\/b2b_product?post=11703"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}