Customizing Blockly's Appearance

We have serveral options for styling blockly: we may create a custom theme, create a custom renderer (or choose between one of the built-in renderers) and we may style blockly directly via css.

By using themes we can change most of the colors of our blocks and components, as well as setting the font used in the blocks.

By using renderers we can customize the shape of the blocks.

By using custom css we can further customize components, beyond just setting their colors and opacities (for example we may set the font that is used in the toolbox)

Themes

Using custom themes allows us to:

  • set the colors (and opacity) of our different block types, as well as the font used in all blocks

  • set the colors (and opacity) of different components, like the background, toolbox, flyout, scrollbar, …

  • set the category color, i.e. the colors that appear next to each category’s name in the toolbox

The image below shows an example of what is possible to achieve, by only creating a custom theme.

blockly workspace, as displayed in the browser, with default ('classic') theme (left) and with a custom theme (right) (note, that on the right side, a background image is used. We cannot directly set a background-image in themes, but we may make the workspace-background transparent, exposing the background underneath)

 

We use JavaScript to define and inject custom themes. The first step is to create a new theme:

const myTheme = Blockly.Theme.defineTheme('nameOfTheme', iTheme};

The first parameter 'nameOfTheme' is used to give our custom theme a name. We can use this name, to customize our theme using css (see the designated css section below). The second parameter iTheme is an object, that contains our styling specifications. We will soon see what kind of specifications we can place in that object. After declaring myTheme, we simply need to inject it into Blockly and we are done:

Blockly.inject('blocklyDiv', { // ... theme: myTheme // ... });

Next, let us see what the structure of the iTheme object looks like. Here is an example object:

const iTheme { base: Blockly.Themes.Classic, // the theme used as a base for our theme blockStyles: { // styling information for our blocks loop_blocks : { colourPrimary: '#CCDD55', colourSecondary: '#FFFFFF' colourTertiary: '#443300', hat: 'cap' }, list_blocks: ... , math_blocks: ... , ... }, categoryStyles : { // color that appears next to the category-name in the toolbox loop_category: { colour: 'rgba(255, 100, 0, 1.0)' }, list_category: ... , math_category: ... , ... }, fontStyle: { // font used in all blocks size: 12, family: 'Titillium', weight: 'bold' }, componentStyles: { // style components (i.e. toolbox, scrollbar, background, ... ) workspaceBackgroundColour: 'rgba(255, 0, 0, 0.0)', scrollbarColour: '#e10072', scrolbarOpacity: 0.5, toolboxBackgroundColour: '#041939', toolboxForegroundColour: '#041939', }, name: 'someName' // unknown usage })

In the example above, we are using the following properties:

  • base : the base-theme that is used for our custom theme

  • blockStyles : an object used for stying blocks. Each property represents a block-type/category. the value for each property is an object that may contain four fields:

    The colourPrimary sets the main color of the block, colourSecondary sets the main color if it is a shadow block and colourTertiary sets the border/highlight (depending on what the the renderer uses) color of the block.

  • categoryStyles : an object used for setting the color that a category appears with in the toolbox. Each property represents a category and the value is an object containting exactly one property 'colour' specifying the color of the selected category. If we have a custom toolbox we may also set the color in the xml that defines the toolbox, f.e. <category name="..." colour="#EB7467">

  • fontStyle : used for specifying the font used in all blocks (it does not seem to affect other texts like f.e. the category names in the toolbar. These must be styled using css)

  • componentStyles : offers a large range of options for altering the appearance of most of blockly’s components (f.e. toolbox, scrollbars, flyout, …). Each option either sets a (possibly fore- or background) color or the opacity of a specific component. The option to set the opacity via a designated property is not available for all components (f.e. the workspace background is missing this option), but notice that we can always provide an rgba-value as color value, f.e.

    allowing us to use the alpha-value to also set the opacity of those components without an explicit opacity option. The full list of options can be found on google’s guide to themes.

 

Renderers

Themes only allow us to set the colors and the font of our blocks, but by using renderers we can also customize their shape. Renderers are used by blockly to render the blocks. Blockly comes with four built-in renderers ('geras', ‘thrasos’, ‘zelos’ and ‘minimalist’), each causing our blocks to have a different appearance. The graphic below compares the four built-in renderers.

The same block, as it is displayed by each of the four built-in renderers. From left to right: geras, thrasos, zelos, minimalist

We specify a renderer by injecting its name (as a string) into blockly:

We may also create custom renderers, which will built upon the 'minimalist' (see image above) renderer . We do this, by creating a new class which extends the Blockly.blockRendering.Renderer base class:

It can be injected the same way as the built-in renderers, only now we have to use our custom name:

A simple way to customize our renderer, is by changing some constants. We can do this by creating new subclass of Blockly.blockRendering.ConstantProvider :

and in order to use our new constant-provider in our custom renderer, we have to override the makeConstants_ method:

In the below image, a block rendererd by our custom renderer is compared to the same block when rendered with 'minimalist' (i.e. the base of our custom renderer).

A full list of constants that we can set in our ConstantProvider subclass can be found here. We can also change the shape of the notches (we could f.e. make them rectangular), but this requires more elaborate changes. For further information see google’s codelab on the topic of renderers.

CSS

Themes and renderers limit us in our options of changing blockly’s appearance. For example, we cannot change the font that is used in the toolbox. As a third option for changing the appearance of blockly’s components, we can directly create css rules, that will apply to blockly’s components. We can access different types of components via the html-classes that blockly uses for them. For example, we can access the labels in the toolbox, that show the block-category's name, with the class blocklyTreeLabel. Note, that if we are in an angular project and we tried to add a rule in the form of

to the <component-name>.component.css file of the angular-component where blockly is located, the styling won’t be applied to the blockly-workspace. This is due to the fact, that when angular builds the application, it changes the selector from .blocklyTreeLabel to .blocklyTreeRow[_ngcontent-...]. One possible fix for this problem is to add the ::ng-deep pseudo-class to the selector:

Here is an example style-sheet, changing the appearance of blockly’s toolbox:

The below image shows how the result looks like in the browser.

 

Blockly also provides us a mechanism, that allows us to provide css that is associated with a specific theme. When defining a theme, we provide a name for the theme:

const customTheme = Blockly.Theme.defineTheme('nameOfTheme', iTheme};

Blockly adds the theme-name as html-class to the injection div:

Notice, that the name is converted to lower case and is postfixed with ‘-theme' (i.e. ‘nameOfTheme' → 'nameoftheme-theme’). By using the .nameoftheme-theme" selector in a css rule, the rule will only be applied if we are currently using the associated theme in blovkly. For example, if we have two themes with the names ‘name1' and 'name2’, that the user may choose between, the following css would associate different font-families with each of the two themes.