Kloudless Blog

Kloudless Unified APIs enable you to code once and integrate many

Our newly introduced Meeting Scheduler UI Tool uses the popular Vue framework to power its single-page app. The Meeting Scheduler helps application developers prompt users to set up meetings with one another.

Our engineers appreciate Vue’s simplicity, growing adoption, and robust ecosystem. The Meeting Scheduler requires several UI components, so we searched for a library to assist with including common widgets such as date-pickers, buttons, and input fields. We chose to use the Vuetify library since we like the material design and built-in components it offers.

Distributing apps built with Vuetify

The Meeting Scheduler is designed to be included in other web applications. However, our choice of Vuetify presents a problem. Vuetify stylesheets pollute global styles and cause a high chance of interfering with the layout of the page they are included in. Here is an excerpt from CSS within Vuetify:

As you can see, Vuetify stylesheets contain global element selectors such as html, *, ::before, and ::after that affect the whole page.

To allow developers to embed our library, we need to ensure that our styles only apply to our own component and don’t impact other elements on the page. There are a couple of options to address this issue.

Use an iframe

An iframe creates a separate page scope, so styles in a component included within an iframe won’t interact with the parent page. However, this also limits the interactions between the component and the parent page, especially if the component is hosted on a different domain. Since our component in this case also optionally launches in a modal, an iframe is not an option.

Use Web Components

Web Components are a new standard to create reusable components. However, the community is continuing to discuss the concept of a local CSS module. For the present time, developers must embed style tags into component templates to include custom styling. Furthermore, it isn’t straightforward to include inline styles in our Webpack build setup. Web Components also require native ES2015 support, which mean end-users using IE11 and Edge are out of luck. We prefer to continue to support these browsers at the present time.

Prefix a master class to each CSS selector

We can create the same effect as a local CSS scope by programmatically wrapping each component inside a root element, and prefixing all CSS selectors with that root element’s class name. This requires additional post-processing to ensure all dependencies’ stylesheets are wrapped, but it provides the best browser compatibility of all the options above. The build process can pre-process all dependencies’ stylesheets.

The Meeting Scheduler CSS Prefix

We wrap the Meeting Scheduler component with a div element that includes a class named kloudless-meeting-scheduler as shown below:

The next step is to process all CSS files and search for selectors. Prefix each line containing a selector with the master class. However, there are some exceptions to watch out for. Consider the styles below:

The snippet above highlights some exceptions:

  • Replace the html selector with the master class instead of adding it as a prefix.
  • Don’t prefix a line that begins with @font-face, @media, or similar.
  • Include a prefix in the @keyframe directive itself for animation properties, and also create a local keyframe name.
  • Don’t touch rules within the @keyframe block.
  • Remember to handle blocks with multiple selectors separated by commas.

Here is an algorithm based on the rules above:

  • Look for lines that don’t begin with @ or end with { or ,.
    • If the selector is html, replace it with MASTER_CLASS. Otherwise, prefix MASTER_CLASS.
  • Look for lines beginning with @-webkit-keyframe or @keyframe.
    • Prefix the keyframe name with MASTER_CLASS-.
    • Ignore the following lines until reaching a line that only contains }.
  • Look for lines with -webkit-animation or animation:
    • Replace the keyframe name with MASTER_CLASS-{name}.

Here’s an implementation in JavaScript:

Here is the result when applied to the styles above:

Keep in mind that this is not a true local scope. For example, it is still possible to pollute page styles by using !important.

Conclusion

We chose to both prefix a wrapper class during the build process as well as provide an iframe URL to developers. This allows most browsers to support our component while providing developers a quick way to embed our library without additional JavaScript.

There are several caveats to implementing the hack shown above; we look forward to using Web Components in the near future once support is wide-spread.

Check out our the final result, the open source Meeting Scheduler, for an easy way to prompt users to schedule meetings with one another.

Categories: