Starcounter
HomeDownloadDocsCommunity
2.3.1
2.3.1
  • Starcounter Documentation
  • Getting Started
  • Starcounter
    • Collapsing the Stack
      • Complexity and Scalability Tradeoff
      • The Future of Micro-Services
      • 10 Benefits of Collapsing the Stack
    • Integrated Database and Web Server
  • Hello World - Tutorial
    • Create a Database Class
    • Create a Real Time UI
    • First Interactive UI
    • Computed Properties
    • Expense Tracker
    • Cancel and Delete
    • The Next Step
  • Guides
    • Database
      • Database Classes
      • Data manipulation
      • Object Identity and Object References
      • Querying with SQL
      • Data Types
      • Relations
      • Inheritance
      • Sharing data
      • Database Configuration
      • Comparing Database Objects
      • Referential Integrity and Constraints
    • SQL
      • Identifiers
      • Path Expressions
      • Data operators
      • Joins
      • Aggregates
      • Comparisons and Logical Operators
      • Sorting
      • Fetch
      • Offset Key
      • Indexes
      • Literals
      • Query Plan Hints
      • Reserved words
      • Query for Database Classes
      • SQL Isolation Between Applications
    • Transactions
      • Short-Running Transactions
      • Long running transactions
      • Using Transactions
      • Running Background Jobs
      • Commit Hooks
    • Typed JSON
      • JSON-by-example
      • Code-Behind
      • Data Bindings
      • Callback Methods
      • Responding with JSON
      • Accepting JSON in Requests
      • Primitive Arrays and Single Value Types
      • Typed JSON Internals
    • Blendable Web Apps
      • Starcounter MVVM
      • Palindrom
      • Client-Side Stack
      • Sessions
      • HTML Views
      • App Shell
      • Web Components
      • View Attaching
      • View Composing
      • HTML Compositions
      • HTML Views Blending Guidelines
      • Avoiding CSS conflicts
      • Debugging
    • Network
      • HTTP
      • Internal Self Calls
      • Middleware
      • Anonymous or Substitute Handlers
      • URL Aliases and Redirects
      • Network Gateway
      • Static File Server
      • External HTTP Calls
      • WebSocket
      • Avoiding URI conflicts
      • TCP Sockets
      • UDP Sockets
    • Publishing Apps
    • Working with Starcounter
      • Release Channels
      • Starting and Stopping Apps
      • Administrator Web UI
      • Star CLI
      • StarAdmin CLI
      • StarDump CLI
      • Working in Visual Studio
      • Error Log
      • Using HTTPS on NGINX
      • Using HTTPS on IIS
      • Run Starcounter in Production
      • Weaver
      • Investigating App Crashes
      • Configuration Structure
      • Database Refactoring
      • Using Unload/Reload to Modify Database Schema
      • Kernel Questions and Answers
      • Log Files
  • Cookbook
    • Attach an HTTP Request to an Existing Long-Running Transaction
    • Cookie-Based Authentication
    • Timestamp on Object Creation
    • Creating Strongly Typed JSON Collections
    • Migrating From 2.2 to 2.3+
    • Multiple Pages
    • Icons
    • Proposed Project Structure
    • Acceptance Testing with Selenium
    • Requesting a User to Authenticate
    • How to delete unused tables and columns
Powered by GitBook
On this page
  • Introduction
  • What is BEM?
  • Example
  • BEM in Starcounter apps
  • Further reading
  1. Guides
  2. Blendable Web Apps

Avoiding CSS conflicts

Introduction

When your system is composed of HTML responses from multiple apps, there's always a risk of naming conflicts and cascading side effects in your CSS. A solution to this is to use a convention that isolates styles coming from different apps.

We recommend BEM, a well-known convention that solves this problem.

What is BEM?

In the BEM naming convention, you only use classes in your stylesheets.  There are three kinds of classes at your disposal: blocks, elements, and modifiers.

A block is a basic class that represents a logical area of your app's UI (a menu, login form, a search form).

An element is a part of a block that performs a particular function (a link in the menu, a password input in the login form, a search icon).

A modifier is a variation of a block or of an element (an expanded menu, an active menu item, a password input with an invalid value, a disabled search button).

Possible combinations of blocks, elements and modifiers are the following:

.block {}
.block__element {} /*The element part starts after __*/
.block--modifier {} /*The modifier part starts after --*/
.block__element--modifier {} /*Both blocks and elements can have modifiers*/

When applied to an HTML structure, the above CSS class names are used in the following way:

<div class="block">
  <div class="block__element"> ... </div>
  <div class="block__element--modifier"> ... </div>
</div>

<div class="block--modifier">
  <div class="block__element"> ... </div>
  <div class="block__element--modifier"> ... </div>
</div>

Note here that everything at the root level must be a block. A block can have multiple element and modifier sections and every element and modifier has to belong to a block.

Example

Here, the block is marked in red and the element sections in blue.

From this, these BEM classes can be derived:

.signin-form {}
.signin-form--expanded {}
.signin-form__text-input {}
.signin-form__labeled-checkbox {}
.signin-form__labeled-checkbox--checked {}

BEM in Starcounter apps

We recommend the following rules when using BEM selectors in Starcounter apps.

  • Only use BEM class selectors in your stylesheets. Do not use element selectors, id selectors, or inline styles for the purpose of styling.

  • Give meaningful names to the block, element and modifier sections. For example, .chatter-avatar is much more descriptive than .chatter-img.

  • Use resusable names for the block, element, and modifier sections. As seen in the example above, .signin-form__text-input is preferred over .signin-form__firstname-input since text-input is more resusable than firstname-input.

  • Prefix block sections with the app name to isolate your classes from other apps. For example, the class for a menu block in the "Chatter" app should be .chatter-menu.

  • Use lowercase classes. .Chatter-Menu is wrong, .chatter-menu is right.

  • Separate words with a hyphen when there are multiple words in a block, element or modifier section. For example: .chatter-chat-message__message-text.

  • Block and element must be in the same HTML template. Otherwise, implicit couplings are created between templates which might break when the partial mapping changes. If you want to define .chatter-menu in a parent partial and the menu items in a nested partials, these menu items will become new blocks (.chatter-menu-item, not .chatter-menu__item).

  • Modifier classes should extend base classes.

    When you set a .chatter-menu__item--active class on an element, it should not be needed to add the .chatter-menu__item base class.

    In your stylesheet, the definition for the base class should include all the modifiers, like this:

    .chatter-menu__item,
    .chatter-menu__item--active {
      font-size: 11px;
    }
    
    .chatter-menu__item--active {
      font-weight: bold;
    }
  • Never nest blocks inside blocks and elements inside elements.

    If there’s need for more nesting, it means there’s too much complexity and the elements should be stripped down into smaller blocks.

  • Mixing BEM with Bootstrap

    Starcounter sample apps use the CSS framework Bootstrap to create a unified look and feel.

    Even though Bootstrap does not follow BEM, there are no issues with mixing Bootstrap and BEM in a single project because there are no collisions. In fact, by just looking at the class, you can immediately tell if that class is shared with other apps (Bootstrap) or if it's private to this particular app (BEM).

    It is not fine to override Bootstrap classes in your app's stylesheet. The only proper way to extend style is to with a BEM selector, for example:

    <ul class="chatter-autocomplete">
      <template is="dom-repeat" items="{{model.FoundAttachment}}">
          <li class="chatter-autocomplete__item">
              <button type="button" class="btn btn-sm btn-link chatter-autocomplete__choose" onmousedown="++this.value;" value="{{item.ChooseTrigger$::click}}">{{item.NameAndType}}</button>
          </li>
      </template>
    </ul>

Further reading

PreviousHTML Views Blending GuidelinesNextDebugging

Last updated 7 years ago

Consider the :

Check out the source code of or . These sample apps show how to apply BEM in practice.

For reference, the available Bootstrap classes can be found in .

SignIn app
People
KitchenSink
bootstrap.css
BEM: Key concepts (bem.info)
Naming convention (bem.info)
BEM-like Naming (cssguidelin.es)
MindBEMding – getting your head ’round BEM syntax (csswizardry.com)
An Introduction to the BEM Methodology (tutsplus.com)