🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
CSS BEM
This page was created by Hans.karlsen on 2019-06-30. Last edited by Wikiadmin on 2026-08-17.

You can use BEM (Block, Element, Modifier) selectors to target a specific MDriven Turnkey control, part of a control, or Designer-assigned style in your CSS.


BEM stands for Block, Element, Modifier. It is a convention on how to structure CSS rules. Read more here.

What BEM means in Turnkey

BEM is a CSS naming convention: Block, Element, Modifier. In Turnkey, the natural block is one control placed from a ViewModel column, widget, or control.

BEM term Meaning in Turnkey Example
Block The outer div for one rendered control. When the ViewModel uses CSS Grid, this is the element placed in the grid. .tk-text-field
Element An inner part of that block. .tk-text-field__label
Modifier An additional class placed on the block through the control's Style ref in MDriven Designer. Use it to express a variation or state. .required, .status-missing

For example, a text field named Name can render as:

<div class="tk-component tk-text-field">
    <label class="tk-text-field__label">Name</label>
    <input class="tk-text-field__native">
</div>

In this example:

  • tk-text-field is the block.
  • tk-text-field__label and tk-text-field__native are elements of that block.
  • tk-component is a common class that Turnkey adds to every BEM block.

Choose the right selector

Use the narrowest selector that expresses the styling intent. Target an element when you need to change only that part of a control; target the block when the whole control needs the same treatment.

Goal Selector Example rule
Style every Turnkey control .tk-component .tk-component { margin-bottom: 0.5rem; }
Style all labels generated inside Turnkey controls .tk-component label .tk-component label { font-weight: 600; }
Style all text-field blocks .tk-text-field .tk-text-field { max-width: 28rem; }
Style only labels in text fields .tk-text-field__label .tk-text-field__label { color: #333; }
Style the editable native input in text fields .tk-text-field__native .tk-text-field__native { border-radius: 0; }
Style one control variation assigned in Designer block and modifier together .tk-text-field.required .tk-text-field__label { font-weight: 700; }

Turnkey block classes

Turnkey assigns the following block class according to the rendered control type. Each block is also assigned tk-component.

Control type Block class
Static text tk-static-text
Image tk-image
Text field tk-text-field
Checkbox tk-checkbox
Date picker tk-datepicker
Combobox tk-select
Grid tk-data-table
Group box tk-groupbox
Button tk-button
File upload tk-file-upload
Link tk-link
Text area (multiline text) tk-textarea
Number field tk-number-field
Float number field tk-float-field

Turnkey element classes

Turnkey uses these suffixes for inner parts of a BEM block:

Element suffix Purpose Example
__native The actual HTML control. .tk-text-field__native
__interactive The part that the user changes. For some controls, such as a checkbox, the native control can be hidden and a different element is used for interaction. .tk-checkbox__interactive
__label The control label. .tk-text-field__label
__content An enclosing inner content div. .tk-groupbox__content

Do not assume that every control renders every element suffix. Inspect the rendered HTML before writing a selector, especially when styling controls with custom presentations.

Add a modifier with Style ref

A modifier is a class that you add in MDriven Designer to distinguish one rendered control from another. Turnkey adds the Style ref as a separate class on the control block.

For example, to mark a Name text field as required:

  1. In the ViewModel Editor, select the ViewModel column or control for Name.
  2. Enter required in the Style ref field.
  3. Add a CSS rule that combines the text-field block with the modifier:
.tk-text-field.required .tk-text-field__label {
  font-weight: 700;
}

.tk-text-field.required .tk-text-field__native {
  border-color: #b00020;
}

The block then includes both classes:

<div class="tk-component tk-text-field required">
    <label class="tk-text-field__label">Name</label>
    <input class="tk-text-field__native">
</div>

This approach keeps the rule limited to required text fields. A rule such as .required would instead affect every element with that class.

Use a dynamic Style ref

You can make a Style ref an expression when the class must depend on ViewModel data. For example, a field can use status-missing when no car is selected and status-selected when a car is selected. Define both classes in your CSS, then have the Style ref expression return the appropriate class name.

.tk-text-field.status-missing .tk-text-field__native {
  border-color: red;
}

.tk-text-field.status-selected .tk-text-field__native {
  border-color: green;
}

Use meaningful class names that describe the UI meaning, such as status-missing, rather than a visual result such as red. This allows you to change the color later without changing the ViewModel expression.

Labels and omitted labels

A label is not always rendered. When a control has no label, Turnkey adds the NoLabel class to the div that encloses the control. Use it when a rule must apply only to controls without labels.

.tk-text-field.NoLabel .tk-text-field__native {
  margin-top: 0;
}

Scope a rule to one ViewModel

Turnkey adds a CSS class named after the ViewModel high in the rendered HTML hierarchy. Combine that class with BEM selectors when a style must apply in one view only.

For a ViewModel named WorkBoard, this rule changes text-field labels only in that ViewModel:

.WorkBoard .tk-text-field__label {
  font-weight: 700;
}

This is preferable to a global .tk-text-field__label rule when other views should retain their existing appearance.

Where to put CSS

BEM selectors describe what to target; they do not determine where CSS is stored or how themes are deployed. Use MDriven Turnkey theming for tkusercss.css, CSS custom properties, and deployment guidance. Use Theme as data when the application supplies CSS from data at runtime.

For page structure, CSS Grid placement, and the surrounding Turnkey layout wrappers, see Documentation:Layout and CSS. For Style ref behavior outside the BEM-specific approach, including formatting and table styling, see HowTos:Styling and CSS for Bootstrap, Angular and MVC.

See also

Our BEM Strategy

CSS rule Comment
.tk-text-field__label.red Match labels for text field controls that has modifier red This is how we do it
.tk-text-field__label--red Match labels for text field controls that has modifier red We do not do this since the above rule is just as easy and requires fewer unique styles
CSS rule Comment
.red tk-text-field__label To match the label intended to be red, we now need to write red in front of the Element specifier - and this a far from what BEM suggests
.tk-text-field__label--red This is what the BEM convention stipulates
.tk-text-field__label.red This is what we do - very BEM-like and true to the general idea of Block__Element--Modifier

Possible Breaking Changes Introduced 2019-06-30

Was Is
.tk-button .tk-button__native
.tk-button.tk-button--narrow .tk-button__native--narrow
.tk-checkbox__label .tk-checkbox__content the style did not target the label surrounding the __native
.tk-checkbox .tk-checkbox__interactive
.tk-data-table .tk-data-table__content the style targets the div containing the table
.tk-data-table__content .tk-data-table__native this is the true table
.tk-select__native-control .tk-select__native native-control should be native as everywhere else
.tk-text-field .tk-text-field__native