This article introduces some CSS layout properties you may not be familiar with, including CSS Writing Modes, CSS Logical Properties, Dynamic Viewport Units, Media Queries Range, `@container` style/size queries, Anchor Positioning, and Break Rules.

## CSS Writing Modes

![CSS writing-mode property examples showing horizontal-tb, vertical-rl, and vertical-lr text directions](https://img.upweb.dev/content/e7a1bb54-1292x470.jpg)

The `writing-mode` property in CSS sets whether text lines are laid out horizontally or vertically and the block's progression direction. When setting this for the whole document, it should be applied to the root element (i.e., the `html` element of the HTML document).

```css
/* Keyword values */
writing-mode: horizontal-tb;
writing-mode: vertical-rl;
writing-mode: vertical-lr;
```

This property can be set for left-to-right (LTR, like English and most other languages) or right-to-left (RTL, like Hebrew or Arabic).

Here’s a clear comparison:

![CSS writing-mode comparison chart showing LTR and RTL text layout differences](https://img.upweb.dev/content/8316795a-1060x573.jpg)

## CSS Logical Properties

![CSS logical properties example showing margin-block-start and padding-inline-end usage](https://img.upweb.dev/content/52fa6e66-1292x534.jpg)

CSS Logical Properties provide a set of properties based on the document's content flow direction, rather than the physical direction used in traditional properties (like `left`, `right`). They automatically adapt to different writing modes, such as left-to-right (LTR) or right-to-left (RTL) languages.

### `margin-block-start` **vs.** `margin-top`

The `margin-block-start` CSS property defines the logical block start margin, which maps to the physical margin depending on the writing mode, directionality, and text orientation.

`margin-block-start`: Sets the margin at the block start. In horizontal writing modes (LTR), it's equivalent to `margin-top`, but in vertical writing modes, it adjusts based on the edge.

It corresponds to `margin-top`, `margin-right`, `margin-bottom`, or `margin-left` depending on the values of `writing-mode`, `direction`, and `text-orientation`.

Related properties include `margin-block-end`, `margin-inline-start`, and `margin-inline-end`, which define other margins for the element.

### `padding-inline-end` **vs.** `padding-right`

Similarly, for padding, the `padding-inline-end` sets the padding for the inline end position. In LTR modes, it's equivalent to `padding-right`, but in RTL modes, it's equivalent to `padding-left`.

### `border-inline-start` **vs.** `border-left`

For borders, the `border-inline-start` defines the border at the inline start position. In LTR writing modes, it's equivalent to `border-left`, while in RTL modes, it becomes `border-right`.

## Dynamic Viewport Units (lvh, lvw, lvmin, lvmax vs. vh, vw)

![CSS dynamic viewport units comparison showing dvh, lvh, and svh differences on mobile browsers](https://img.upweb.dev/content/c6160390-1292x595.jpg)

The traditional `vh` and `vw` units define sizes as a percentage of the viewport. For example, "100vh" is 100% of the viewport height, and "50vw" is 50% of the viewport width.

However, the problem with `vh` and `vw` units is that your app doesn't always have access to the full viewport, especially on mobile devices, where browser controls (like the address bar) take up space. This means a "100vh" element can overflow, causing part of the content to be hidden when browser controls are visible. You could work around this with `height: calc(100vh - <location bar height in px>)`, but that could break if the browser updates.

Now, this issue can be solved with new viewport units:

- **Small viewport (**`svh`, `svw`, `svmin`, `svmax`): These units provide the height, width, minimum, and maximum dimensions of the viewport when the browser chrome is visible (e.g., on page load or after scrolling to the top).
- **Large viewport (**`lvh`, `lvw`, `lvmin`, `lvmax`): These units represent the viewport when the browser chrome is hidden (e.g., after scrolling down the page).
- **Dynamic viewport (**`dvh`, `dvw`, `dvmin`, `dvmax`): These units dynamically switch between the small or large viewport, depending on whether the browser chrome is visible. This means it uses `lvh` when the address bar is hidden and `svh` when it's visible.

The dynamic viewport is the most useful. Here's an example of adjusting the page size based on browser UI changes:

```css
.body {
  height: 100dvh;
}
```

Small and large viewport units also have their use cases. For instance, adjusting font sizes based on viewport size, such as setting headings to `10svh`, ensures text doesn't scale too much when users enter fullscreen.

## Media Queries Range Contexts

![CSS media queries range context syntax example showing simplified width range definitions](https://img.upweb.dev/content/4ebd9f9a-1292x579.jpg)

Media query range contexts allow developers to define responsive conditions more intuitively, using simple syntax for defining a range, instead of writing multiple complex media queries.

Here's the traditional syntax:

```css
@media (min-width: 400px) and (max-width: 1000px) {
  /* Styles apply between 400px and 1000px viewport width */
}
```

With range context, you can now write:

```css
@media (400px < width < 1000px) {
  /* Range context */
}
```

## @container Style/Size Queries

![CSS container queries example demonstrating @container rule for component-based responsive design](https://img.upweb.dev/content/1348669a-1292x567.jpg)

The `@container` rule allows queries based on the container's size or style, making styling more flexible instead of relying on viewport size. This means the condition is reevaluated when the container's size or `<style-feature>` changes.

Here's the syntax:

```css
@container <container-condition> {
  <stylesheet>
}
```

Examples:

```css
@container <container-condition># {
  <stylesheet>
}

/* Example usage of a basic container query */
@container (width > 400px) {
  h2 {
    font-size: 1.5em;
  }
}

/* You can set a container name and apply styles only to containers matching that name */
.post {
  container-name: sidebar;
  container-type: inline-size;
}
/* Or use the shorthand syntax */
.post {
  container: sidebar / inline-size;
}

/* Example with an optional <container-name> */
@container sidebar (height > 30rem) {
  h2 {
    line-height: 1.6;
  }
}

/* Multiple queries in a single condition */
@container (width > 400px) and style(--responsive: true) {
  h2 {
    font-size: 1.5em;
  }
}
```

While traditional media queries target the entire viewport, `@container` only applies to a specific container, making it especially useful for component-based development and responsive layouts.

## Anchor Positioning

![CSS anchor positioning example showing dynamic element connection and relative positioning](https://img.upweb.dev/content/06c7f3a6-1292x499.jpg)

Anchor positioning lets you connect elements together so they can adjust based on each other. Some elements are defined as anchor elements; other elements can be positioned relative to them.

This is useful for dynamic positioning, such as menus, tooltips, selects, labels, and settings dialogs, eliminating the need for third-party libraries.

For example, you can define an anchor name with `anchor-name`, and other elements can position themselves relative to it:

```css
.slider-link {
  anchor-name: var(--anchor1); /* Define an anchor */
}

/* Other elements can position themselves relative to the anchor */
.related-element {
  position-anchor: --anchor1;
  position: absolute;
  right: anchor(right);
  bottom: anchor(top);
}
```

![CSS anchor positioning advanced example demonstrating position-anchor and anchor function usage](https://img.upweb.dev/content/e51e8df7-1366x725.jpg)

More details on [web.dev](https://web.dev).

## Break Rules

![CSS break rules example showing break-after, break-before, and break-inside for page layout control](https://img.upweb.dev/content/17981aa2-1292x416.jpg)

Break rules control how elements break across pages, columns, frames, or text regions, especially useful in print layouts or complex multi-column layouts. These rules give developers more control over text flow in paginated or constrained layouts.

The three properties are `break-after`, `break-before`, and `break-inside`.

`break-after` sets how breaks should behave after a generated box. If no box is generated, the property is ignored. `break-before` applies similarly but before the box.

```css
break-after: auto; /* Allows a break after the box */
break-after: avoid; /* Avoids breaks after the box */
break-after: always; /* Forces a break after the box */
break-after: all; /* Forces a break in all contexts */
```

`break-inside` controls whether elements can break inside, preventing content from splitting across columns or pages.

```css
break-inside: auto; /* Allows breaks inside */
break-inside: avoid; /* Avoids breaks inside */
break-inside: avoid-page; /* Avoids page breaks inside */
break-inside: avoid-column; /* Avoids column breaks inside */
```

_If you found this helpful, consider [subscribing to my newsletter](https://upweb.dev) for weekly web development insights and updates. Thanks for reading!_
