Any ideas why the bottom stroke of a block goes under the fill of the next block?

In the following example:

#set page(margin: 1cm)

= Block Strokes

== `v(5pt)` spacing between blocks

#block(
  width: 100%,
  above: 0pt,
  below: 0pt,
  inset: 5pt,
  fill: aqua,
  stroke: (bottom: 1pt + blue),
  [Block 1]
)
#v(5pt)
#block(
  width: 100%,
  above: 0pt,
  below: 0pt,
  inset: 5pt,
  fill: aqua,
  stroke: (bottom: 1pt + blue),
  [Block 2]
)

#v(10pt)

== No `v` spacing between blocks (Block 3's stroke is clipped)

#block(
  width: 100%,
  above: 0pt,
  below: 0pt,
  inset: 5pt,
  fill: aqua,
  stroke: (bottom: 1pt + blue),
  [Block 3]
)
#block(
  width: 100%,
  above: 0pt,
  below: 0pt,
  inset: 5pt,
  fill: aqua,
  stroke: (bottom: 1pt + blue),
  [Block 4]
)

#v(10pt)

== `v(1pt)` spacing between blocks (There's some white space between blocks 5/6)

#block(
  width: 100%,
  above: 0pt,
  below: 0pt,
  inset: 5pt,
  fill: aqua,
  stroke: (bottom: 1pt + blue),
  [Block 5]
)
#v(1pt)
#block(
  width: 100%,
  above: 0pt,
  below: 0pt,
  inset: 5pt,
  fill: aqua,
  stroke: (bottom: 1pt + blue),
  [Block 6]
)

Why is Block 3’s 1pt stroke is partially covered by Block 4? Is there something like CSS’s box-sizing: border-box (or any other feature) that ensures Block 4 does not overlap Block 3?

This is more visible when the document is exported to PDF:

The stroke is centered on the edge of the block. If you are using a stroke width of 1pt, only half of that sticks out of the block. This a lot easier to see if you set the stroke width to something big, e.g. 1cm. The correct spacing for your blocks 5 + 6 would, therefore, be 0.5pt.

2 Likes

Another way to draw the complete stroke is to adjust the outset parameter of the block. Basically adjust the center of the stroke inwards by half the stroke width.
This results in blocks of different height, however. See the comparison here:

Placing a space between probably has fewer unexpected consequences, though it depends what the application is.

Full Code
#set page("a7")
#set page(height: auto)
#set page(margin: 1em)

#let stroke-width = 1pt

#let b = block.with(
  width: 100%,
  above: 0pt,
  below: 0pt,
  inset: 5pt,
  fill: aqua,
  stroke: (bottom: 1pt + blue)
)

#let block-outset = [
  #b(
    outset: (bottom: -(stroke-width / 2), rest: 0pt),
  )[Block 3]
  #b(
    outset: (bottom: -(stroke-width / 2), rest: 0pt),
  )[Block 4]
]

#let block-space-between = [
  #b[Block 5]
  #v(stroke-width / 2)
  #b[Block 6]
]

#grid(
  columns: 2,
  gutter: 0.5pt,
  row-gutter: .5em,

  [Outset],
  [Space between],

  block-outset,
  block-space-between
)
3 Likes