Tutorials

Table of contents
Close

Making sure your CSS/JS works well in the HubSpot CMS editors

The HubSpot CMS editors provide an inline editing experience to help content authors create and edit their content in a what you see is what you get (WYSIWYG) fashion. To accomplish this, the editors include an iframe with a preview of the webpage that includes both code from modules and templates as well as HubSpot application CSS/JS. Sometimes CSS/JS from a template or module causes problems in the editors. This article is a guide on best practices to avoid those problems.

 

Testing in the editor

It’s important to test your developed assets in HubSpot’s content editors before delivering them. Testing in the editor is a good way to spot styling conflicts with the editor and to create a seamless experience for your end user.

The following are a sampling of tests that can be run in the editor:

  • Format text via Style dropdown options (i.e. font, text size) and toolbar options (i.e. alignment, colors)

  • Click to insert options from Rich Text toolbar (i.e. embed, link, image, personalization tokens)

  • Click on the rich text elements plugins (i.e. embed, link, image, personalization tokens) in the inline editors and make sure that the UI works correctly and appears as expected.

 

Be specific

Broadly speaking, issues in the content editor can arise when custom JavaScript or CSS is not specific enough. This manifests differently depending on how the code is written, and the risk of custom code interfering with the editor is ever present. Consider this function as an example.



$('body').click(function(event){

  $('.blog-listing-wrapper .post-listing .post-item').siblings().find('.right').removeClass('social-active');

  event.stopPropagation();

});

This function will run when there’s a click on the body element. Because the code calls event.stopPropagation(), the event will not bubble up to the document or window. If there are event listeners on those elements, the code in those listeners will not run. The issue with the above code is that the click handler will run on every click, which causes problems in the inline editor because it adds click handlers to the window element via React. Instead of listening for every click, it would be more appropriate to only add the click handler when needed — for example, after a user has clicked a button to open a side menu — and then removing the handler once the click has fired.

Problems can also occur in CSS when using selectors that are generic like label. When possible it is preferred to use selectors that are specific to a portion of the webpage such as .hs-form label.

 

Avoid using !important tags

!important tags are used to make styling rules take precedence over others. Use of !important tags on bare element selectors like label or input[type="text"] are not best practice when building web content, but they are often used when a style rule is being overridden by something more specific than the selected rule. Using !important will help the selected rule rise to the surface and be the winning style rule on a given asset, even if it’s less specific.

Instead, favor specificity in your selectors so that you don’t have to use !important. This will allow you to pinpoint the elements you’re looking to style without putting blanket rules over things beyond the element you’re targeting. You can also take advantage of our boilerplate CSS file to have a better sense of selectors that should be used to avoid CSS bleed issues.

How to avoid using !important

Sometimes, !important is used in CSS for the <label> element, with the intent to ensure that all <label> elements in a form are white:


label, legend {
   color: white !important;
}

Despite the intent, using an element as a selector for the style rule is too broad, making all <label> tags in the content editor white. This style rule doesn’t exclude the <label> elements used in our insert link plugins, resulting in the illusion of missing labels for fields on our plugin.    

white plugin fields

Instead, you can use more specific selectors, as we did in the style rule below, to target the labels for the form module you’re seeking to add the white color to so this will not affect the labels elsewhere in the content editor. This is a great resource for developers looking to get a better sense of what selectors can be used when styling a form.


.hs-form label, .hs-form .hs-form-field > label, .hs-form .hs-field-desc {
    color: white;
}

 

Using .hs-inline-edit & window.hsInEditor

The editor uses an iframe to load a preview of the content into HubSpot’s content editor. To this iframe, .hs-inline-edit is a class that is added to the <html> element and window.hsInEditor is defined to `true`. When the inline editor is initialized, these items give developers the opportunity to determine if the content is within the HubSpot content editor.

Developers can use the .hs-inline-edit class to write CSS that does not apply when the web page is loaded in the editor to avoid CSS bleed. If the issue is with JavaScript impacting the inline editing experience, developers can use the window.hsInEditor variable to disable portions of their code when the code is run inside the editor.

How to use .hs-inline-edit:

Preface selectors that want to scope your rules to apply only inside of the editor with .hs-inline-edit.

For example, the following CSS takes advantage of the psuedo selector :not():


:not(.hs-inline-edit) label {

   color: white;

}

Alternatively, you can take advantage of the HubSpot specific class.

For example, if you have a fixed header in your page and are seeing that the fixed rich text toolbar in the editor is getting hidden underneath the fixed header, you're probably pushing your website's UI layers to the highest z-index. Generally it's not good practice to do this (unless you absolutely have to). Within the editor it becomes particularly problematic as your content can render on top of the inline controls. We recommend keeping your websites' UI layers beneath [X] z-index for best results, for which you can use the selector .hs-inline-edit, followed by the selector for your fixed header (i.e. header), and employ the z-index value of 2147483599:


.hs-inline-edit .header {

    z-index: 2147483599;
    
}

How to use window.hsInEditor:

To ensure that the JavaScript functions will fire after the editor is loaded, including conditionals that use window.hsInEditor to determine whether or not to do something would be helpful. Consider the one pasted below that takes advantage of the jQuery document ready handler:


jQuery(document).ready(function($) {
  if (window.hsInEditor) {
    return;
  }
  // so other stuff
  $('.some_widget').fancyThing();
});