Blockly applications are constructed of HTML and SVG elements. These elements
are labeled with CSS classes that identify what they represent (e.g.
blocklyBlock
, blocklyField
) as well as their state (e.g. blocklyEditing
,
blocklySelected
). Blockly also provides a default set of CSS rules.
You can use CSS to style your application:
- Override Blockly's CSS rules with your own rules.
- Add your own CSS classes to Blockly components for additional specificity.
- Use CSS classes and rules to style custom components.
CSS classes
Blockly applications use CSS classes to identify elements to be styled. This provides finer-grained control than type (element) selectors.
Blockly CSS classes
Blockly uses CSS classes to provide the following kinds of information about the HTML and SVG elements it uses.
Type. Most Blockly CSS classes identify what an element represents. For example, the root element of a block is labeled
blocklyBlock
. Some elements are labeled with multiple classes, each more specific than the last. For example, the root element of a text input field is labeledblocklyField
,blocklyInputField
, andblocklyTextInputField
. Type classes remain the same for the life of a component.State. Blockly also uses CSS classes to specify the state of a component. For example, when the cursor is on a text input field, its root element is labeled with the
blocklyEditing
class. When the cursor is moved away, this class is removed.Additional information. Blockly uses a few CSS classes to provide additional information. For example, the injection
<div>
has classes that provide the name of the workspace's current renderer and theme. These classes generally remain the same for the life of the application.
The easiest way to discover what CSS classes Blockly uses is to open your browser's developer tools and inspect the elements used by your application.
Custom CSS classes
You can use custom CSS classes to provide more specificity to Blockly components.
Workspaces
To add or remove a CSS class from a workspace's injection <div>
, call
WorkspaceSvg.addClass
or WorkspaceSvg.removeClass
.
Toolboxes
To add a CSS class to a button or a label in a toolbox, use the web-class
key
in your JSON definition of the toolbox. For more information, see Buttons and
labels.
To override the CSS classes used for the various parts of a category, use the
cssConfig
key in your JSON definition of the category. This allows you to
style individual categories. For more information, see Category
CSS.
Blocks
To add CSS classes to a custom block, pass a string or array of strings to the
classes
key.
Blockly.common.defineBlocksWithJsonArray([{
"type": "string_length",
"message0": 'length of %1',
"args0": [
{
"type": "input_value",
"name": "VALUE",
"check": "String",
}
],
"classes": "myStringLengthBlock",
"output": "Number",
"colour": 160,
}]);
You can also add or remove a CSS class from a block's <g>
element by calling
BlockSvg.addClass
or BlockSvg.removeClass
.
Label fields
To add or remove a CSS class from the <text>
element used by a label field or
serializable label field, call FieldLabel.setClass
. You can also pass a class
name to the label's constructor.
CSS classes and custom components
When constructing a custom component, use one of the following methods to add custom CSS classes:
If your component is a subclass of
Field
orIcon
, override theinitView
method. For example:class MyCustomField extends Blockly.FieldTextInput { ... initView() { super.initView(); // Add custom CSS class so we can style the field. if (this.fieldGroup_) { Blockly.utils.dom.addClass(this.fieldGroup_, 'myCustomField'); } } }
For more information, see Customizing fields with CSS or Create the icon's view.
When constructing an SVG element, pass your class to
Blockly.utils.dom.createSvgElement
:this.svgRoot = Blockly.utils.dom.createSvgElement(Svg.G, {'class': 'myCustomComponent'});
When constructing an HTML element, use
Blockly.utils.dom.addClass
:const myDiv = document.createElement('div'); Blockly.utils.dom.addClass(myDiv, 'myInformation');
To add or remove classes after construction, use Blockly.utils.dom.addClass
or
Blockly.utils.dom.removeClass
.
setMyHighlight(highlight) {
if (highlight) {
Blockly.utils.dom.addClass(this.svgRoot, 'myHighlight');
} else {
Blockly.utils.dom.removeClass(this.svgRoot, 'myHighlight');
}
}
CSS rules background
If you understand SVG styling properties and the CSS cascade, you can skip this section.
SVG styling properties versus CSS properties
SVG elements are styled with SVG styling properties. These can be used as attributes on SVG elements (aka presentation attributes) or in CSS rules. Thus, all of the following do the same thing.
<!-- SVG file with presentation attributes. -->
<circle fill="red" ... />
<!-- SVG file with <style> tag. -->
<style>
circle {fill:red;}
</style>
<circle ... />
/* External CSS file.*/
circle {fill:red;}
<!-- SVG file with inline style. -->
<circle style="fill:red;" ... />
The list of SVG styling properties is related to but different from the list of CSS properties:
- Same concept, same name. For example, both SVG and CSS use
direction
to specify whether text is LTR or RTL. - Same concept, different name. For example, SVG uses
fill
to specify fill color; CSS usesbackground-color
. - CSS only. CSS has many properties that are not in SVG, such as
margin
andpadding
. - SVG only. SVG has a few properties that are not in CSS, such as
x
andy
.
Thus, if you're styling an SVG element, use SVG styling properties. If you're styling an HTML element, use CSS properties.
CSS cascade
The CSS cascade determines the priorities of CSS rules, which determine which rule to use if more than one rule applies to a given property and element. The following simplified cascade covers the parts of the cascade most commonly used by Blockly and may help you resolve the question, "Why doesn't my CSS work?"
Simplified cascade
To determine which rule applies to a particular element and property, follow these steps and stop when only one rule remains:
- Gather all the rules that apply to the property and element.
- If any rules have an
!important
annotation, discard all rules that don't have an!important
annotation. Choose the rules with the highest specificity.
- SVG presentation attributes have a specificity of zero.
- Rules in a
<style>
tag or external stylesheet have their specificity calculated normally. - Inline styles (styles set by a
style
attribute) have a specificity higher than any selector.
Choose the rule that appears last in the document.
If no rule applies, inherit the property's value from the element's parent.
This algorithm does not consider the following parts of the cascade:
- The
transition
property, which has the highest priority. Blockly uses a few of these. - The
@media
at-rule. Blockly uses one of these. - Rules specified by the browser or user.
- The
@scope
and@layer
at-rules and theanimation
property, which are not used by Blockly.
CSS rules
CSS rules specify how your application is styled. Blockly provides a default set of rules that you can override with your own rules.
Blockly CSS rules
Blockly provides a default set of CSS rules. How and where these rules are added affects their priority.
Style tags
The majority of Blockly's CSS rules are specified in two <style>
tags. Because
these tags occur near the top of the page, the rules in them have lower priority
than rules with the same specificity that occur later in the page.
Blockly.css.register rules
When Blockly is injected, it adds a <style>
tag as a child of the <head>
tag. The rules in this tag come from:
- The
Blockly.css
namespace. To see these rules, open core/css.ts and search forlet content
. - Individual components, which call
Blockly.css.register
to add component-specific CSS rules. Becausecss.register
adds these rules to the end of thecontent
string, they have higher priority than rules with the same specificity that were added earlier. To see these rules, see the calls toBlockly.css.register
.
If you do not want to use these rules, set the css
configuration
option
to false
. In this case, you are responsible for providing an alternate set of
CSS rules.
Renderer rules
When the renderer is instantiated, it adds a <style>
tag containing
renderer-specific CSS rules as a child of the <head>
tag. Note that these
rules are always added -- they are not affected by the css
configuration
option. To see these rules, search for the getCss_
method in your renderer.
Inline styles
Inline styles are specified with the style
attribute and are generally created
when the DOM for a component is created. For a partial list, see this GitHub
query.
Inline styles apply directly to the element on which they occur and have a
specificity higher than any selector. For this reason, overriding them generally
requires you to use an !important
annotation.
SVG presentation attributes
SVG presentation attributes are SVG styling properties used as
attributes of SVG elements. They have a specificity of zero and cannot contain
an !important
annotation, so they have the lowest priority of all of Blockly's
rules. Blockly generally creates them in calls to
createSvgElement
.
Add your own CSS rules
You can add your own CSS rules using the same methods as Blockly:
- Call
Blockly.css.register
before injecting Blockly. Your rules will be added after Blockly's and have a higher priority than Blockly rules with the same specificity. - Add a
<style>
tag or link to an external style sheet as a later child of the<head>
tag. Because Blockly adds its rules as the first two children of the<head>
tag, your rules will have a higher priority than Blockly rules with the same specificity. - Use inline styles to add styles to elements in a custom component. These rules will have a higher specificity than any rules with a selector.
- Use presentation attributes on SVG elements in a custom component. These rules will have a lower specificity than any rules with a selector.
Troubleshooting
If your CSS is not working, here are some possible causes:
You are using CSS properties on an SVG element or SVG styling properties on an HTML element. See SVG styling properties versus CSS properties.
Your rule has a lower priority than another rule. This is usually due to a lower specificity. Possible ways to fix this are:
- Use a class selector instead of a type (element) selector.
- Use multiple selectors.
- If possible, add a custom class to your target element and use this class in your rule.
- As a last resort, add an
!important
annotation to your rule. This is your only choice if a competing rule is specified using an inline style (style
attribute).
Your rule has the same specificity as another rule, but occurs earlier in the page. If you cannot increase the specificity of your rule, move it later in the page.
There are two types of CSS rules you cannot override:
- Properties that are set inside a
transition
rule. !important
rules specified by the browser.