Skip to Content
Technical Articles
Author's profile photo Dominik Schreiber

How to import files from theming-base-content without inlining all urls using postcss

Using the open-source npm module @sap-theming/theming-base-content makes it surprisingly easy to use all SAP Fiori theming parameters in your own applications. Especially you can simply import the css_variables.css file of the theme you want and start using the custom CSS properties.

Depending on your build setup, this may have unintended side-effects. One side-effect has been raised in CSS variable files should differentiate between variables and variables that load assets: with a default bundler configuration that inlines assets into the bundled CSS file, all assets referenced by the css_variables.css file are inlined as well. As many fonts (all versions of the 72 font, and the SAP-icons) are referenced, this results in unnecessary large bundle sizes.

In this post I show how to configure postcss, the de-facto CSS bundler standard, to inline imports and assets, but ignore the assets referenced in css_variables.css.

Repository setup

Let’s start from scratch.

mkdir my-project && cd my-project
npm init -y
npm i -S @sap-theming/theming-base-content

With that we get a new directory my-project in which we’ll be working, that contains an empty package.json which then gets @sap-theming/theming-base-content as a regular dependency.

We will create a src/main.css which we’ll be editing, and which should be bundled to target/main.css. For demonstration purposes we’ll import the css_variables.css of Morning Horizon from @sap-theming/theming-base-content (which will contain asset URLs we don’t want to inline) and add a url to our own code (which we do want to inline).

/* file: src/main.css */
@import url("@sap-theming/theming-base-content/content/Base/baseLib/sap_horizon/css_variables.css");
.checkers {
  background-image: url("./checkers.svg");
}

For the sake of completion, src/checkers.svg just creates black and white tiles:

<!-- file: src/checkers.svg -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <rect x="0" y="0" width="50" height="50" fill="#000"/>
  <rect x="0" y="50" width="50" height="50" fill="#fff"/>
  <rect x="50" y="0" width="50" height="50" fill="#fff"/>
  <rect x="50" y="50" width="50" height="50" fill="#000"/>
</svg>

Adding postcss

To bundle src/main.css we’ll be using postcss-cli with the plugins postcss-import (to inline the @import) and postcss-url (to inline the url()).

npm i -D postcss-cli postcss-import postcss-url

We want to bundle src/main.css to target/main.css, so we’ll be calling

npx postcss src/main.css -o target/main.css

To add plugins to that we need a postcss.config.js in the project root. The magic part is that postcss-url is applied only to urls inside the src/ folder.

// file: postcss.config.js
module.exports = {
  plugins: [
    require('postcss-import')(),
    require('postcss-url')({filter: 'src/**/*', url: 'inline'})
  ]
}

Now if we run postcss, css_variables.css is inlined, checkers.svg is inlined, but the assets referenced in css_variables.css are not. Just as we intended:

/* file: target/main.css */
/**
* Copyright (c) 2012-2020 SAP SE or an SAP affiliate company. All rights reserved.
*
* Theming Engine 1.69.2
* data:{"Path": "Base.baseLib.sap_horizon.css_variables", "PathPattern": "/%frameworkId%/%libId%/%themeId%/%fileId%.css", "Extends": ["baseTheme"], "Tags": ["Fiori_3","LightColorScheme"], "FallbackThemeId": "sap_fiori_3", "Engine": {"Name": "theming-engine", "Version": "1.69.2"}, "Version": { "Build": "11.1.38.20220405122918", "Source": "11.1.38"}}
*/

.sapThemeMetaData-Base-baseLib{background-image: url('data:text/plain;utf-8,{"Path": "Base.baseLib.sap_horizon.css_variables", "PathPattern": "/%frameworkId%/%libId%/%themeId%/%fileId%.css", "Extends": ["baseTheme"], "Tags": ["Fiori_3","LightColorScheme"], "FallbackThemeId": "sap_fiori_3", "Engine": {"Name": "theming-engine", "Version": "1.69.2"}, "Version": { "Build": "11.1.38.20220405122918", "Source": "11.1.38"}}');}

:root{--sapThemeMetaData-Base-baseLib:{"Path": "Base.baseLib.sap_horizon.css_variables", "PathPattern": "/%frameworkId%/%libId%/%themeId%/%fileId%.css", "Extends": ["baseTheme"], "Tags": ["Fiori_3","LightColorScheme"], "FallbackThemeId": "sap_fiori_3", "Engine": {"Name": "theming-engine", "Version": "1.69.2"}, "Version": { "Build": "11.1.38.20220405122918", "Source": "11.1.38"}};}

:root {
  --sapBrandColor: #0070f2;
  --sapHighlightColor: #0070f2;
  --sapBaseColor: #fff;
  /* […] */
  --sapFontUrl_72Mono_Bold_woff: url('../../../Base/baseLib/baseTheme/fonts/72Mono-Bold.woff');
  --sapFontUrl_72Mono_Bold_full_woff2: url('../../../Base/baseLib/baseTheme/fonts/72Mono-Bold-full.woff2');
  --sapFontUrl_72Mono_Bold_full_woff: url('../../../Base/baseLib/baseTheme/fonts/72Mono-Bold-full.woff');
}

.background-image--sapCompanyLogo {
  background-image: var(--sapCompanyLogo);
}

.background-image--sapBackgroundImage {
  background-image: var(--sapBackgroundImage);
}

.background-image--sapShell_BackgroundImage {
  background-image: var(--sapShell_BackgroundImage);
}

.checkers {
  background-image: url("data:image/svg+xml,%3Csvg xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22 viewBox%3D%220 0 100 100%22%3E  %3Crect x%3D%220%22 y%3D%220%22 width%3D%2250%22 height%3D%2250%22 fill%3D%22black%22%2F%3E  %3Crect x%3D%2250%22 y%3D%220%22 width%3D%2250%22 height%3D%2250%22 fill%3D%22white%22%2F%3E  %3Crect x%3D%2250%22 y%3D%2250%22 width%3D%2250%22 height%3D%2250%22 fill%3D%22black%22%2F%3E  %3Crect x%3D%220%22 y%3D%2250%22 width%3D%2250%22 height%3D%2250%22 fill%3D%22white%22%2F%3E%3C%2Fsvg%3E");
}

Recap

This shows that it is possible with proper bundler configuration to inline everything but the assets from css_variables.css.

As a little exercise we can add a second filter to postcss-url, that rewrites all URL references from css_variables.css to absolute URLs against the unpkg.com CDN:

// file: postcss.config.js
module.exports = {
  plugins: [
    require('postcss-import')(),
    require('postcss-url')([
      {filter: 'src/**/*', url: 'inline'},
      {filter: '**/content/Base/baseLib/**/*', url: ({url}) => `https://unpkg.com/@sap-theming/theming-base-content/content/Base/baseLib/${
        url.replace(/^.*\/content\/Base\/baseLib\//, '')
      }`}
    ])
  ]
}

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.