Skip to content

Consider making box-sizing: border-box the default for Blockly v13 #9205

@cpcallen

Description

@cpcallen

Check for duplicates

  • I have searched for similar issues before opening a new one.

Problem

The CSS attribute box-sizing affects how box dimensions are computed, and unfortunately for default value, content-box, is not ideal in most situations when trying to size one item inside another.

One example of where this becomes an issue is when trying to add a border around the toolbox to denote that it is focused: by default the sizing of the toolbox does not take the border into account, so the toolbox gets a few pixels wider and taller. The width isn't a big problem: it just pushes lightly further into the workspace—but the height is, because the bottom edge of the toolbox gets cut off by the overall size of the workspace:

Image

This specific issue is being fixed in #9201 (having previously been fixed with a much larger hammer in google/blocly-keyboard-experimentation#511) , but Blockly has had to apply box-sizing: border-box to a number of elements in order for them to be sized correctly.

This annoyance is so common in web design that many app stylesheets and some CSS resets include something like:

*, *::before, *::after {
  box-sizing: border-box;
}

in order to ensure that the attribute defaults to border-box everywhere—and note that box-sizing is not inheritable, so hence the need for wildcards here.

Because of the poor default value, the non-inheritability, and therefore likelihood that an app author will use a wildcard selector like * to apply box-sizing: border-box to their entire app, Blockly cannot rely on the value of the box-sizing attribute unless we set it directly.

Request

I propose that we include the following style in core/css.ts:

:is(
  .injectionDiv,
  .blocklyWidgetDiv,
  .blocklyDropdownDiv,
  .blocklyTooltipDiv,
) * {
  box-sizing: border-box;
}

This should have the effect of setting box-sizing to border-box on every element of Blockly, without affecting any of the surrounding app.

N.B.: This is a breaking change, because it applies box-sizing: border-box to everything within Blockly, including plugins and developer-supplied custom field editors, etc., which might (in principle at least) depend on the default box-sizing: content-box.

Alternatives considered

Setting box-sizing globally

We could add * {box-sizing: border-box} to core/css.ts, and this would certainly take care of the problem but would also change the default for the entire page, which we should definitely avoid.

Inheriting box-sizing:

An alternative to consider would be change the default for blockly by applying the attribute to the top-level divs and making it inherited by the rest of the app:

.injectionDiv, .blocklyWidgetDiv, .blocklyDropdownDiv, .blocklyTooltipDiv,html {
  box-sizing: border-box;
}

:is(
  .injectionDiv,
  .blocklyWidgetDiv,
  .blocklyDropdownDiv,
  .blocklyTooltipDiv,
) :is (* *, *:before, *:after) {
  box-sizing: inherit;
}

which would facilitate opting-out any plugins/components that actually rely on the CSS default: it would only be necessary to add box-sizing: content-box to the containing element and the contents would all be opt-ed out.

This however still requires an explicit opt-out for any component actually depending on the CSS defaut value, so it's not a panacea to avoid breaking changes.

Continuing to only set box-sizing where specifically needed

This has two main disadvantages:

  • We will continue to run into problems where layout is wrong until we explicitly add box-sizing: border-box.
  • If there are any parts of blockly that (intentionally or otherwise) depend on the default box-sizing: content-box, they are likely to be broken by app developers specifying a global default of border-box, since they will do so by wildcard.

Additional context

There have been a few issues which were caused by the bad default value for box-sizing, e.g.:

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions