Riccardo Ventura

Design Engineer

Best practices

Concentric radius

5'

Il problema negli angoli

In una card, un menu o un campo di ricerca, lo spazio fra due bordi arrotondati deve restare regolare anche negli angoli. Quando si lavora in fretta capita di dare lo stesso border-radius al contenitore e all'elemento interno. Il componente funziona e a prima vista il difetto può sfuggire. Negli angoli, però, le due curve non hanno lo stesso centro1.

Sbagliato

Giusto

Nell'esempio con raggi uguali lo spazio fra le curve si allarga negli angoli. Paul Hebert, di Cloud Four2, se n'è accorto così: aveva usato lo stesso valore per entrambi gli elementi e il risultato sembrava comunque storto.

Calcolare il raggio interno

Per mantenere uniforme lo spazio, il raggio interno deve diminuire della distanza fra i due bordi. In Figma o in Paper puoi ottenere questa relazione con un offset; nel codice puoi calcolarla:

raggio interno = raggio esterno − spazio

La formula

Hebert propone di pensare a ogni angolo come a un piccolo cerchio: border-radius ne imposta il raggio. Ora immagina due quarti di cerchio con lo stesso centro, uno dentro l'altro. La differenza fra i raggi è la distanza fra le curve, ed è per questo che lo spazio resta uguale lungo tutto l'angolo.

Due quarti di cerchio con lo stesso centroI raggi R e r hanno lo stesso centro. Il segmento blu g, sull'asse verticale e su quello orizzontale, mostra la loro differenza: R meno r.centroRrg

r = max(R − g, 0)

Qui R è il raggio esterno, r quello interno e g la distanza fra i due bordi. Finché la sottrazione dà un valore maggiore o uguale a zero, puoi leggere la relazione anche come R = r + g. Se il contenitore non ha un bordo, g coincide con il padding; se ce l'ha, g comprende anche il suo spessore.

R
raggio del bordo esterno
r
raggio del bordo interno
g
distanza tra i due bordi

R32px

g12px

r20px

La distanza fra le due curve resta 12pxanche nell'angolo.

Il codice

Nel codice conta tutta la distanza fra le due curve. Il border-radius del contenitore definisce il raggio esterno4. Per trovare quello dell'elemento interno togli lo spessore del bordo, se c'è, e poi il padding. È lo stesso ordine della specifica W3C3: prima il bordo, poi il padding.

<div className="rounded-[32px] border-4 border-solid border-current p-3">
  <div className="rounded-2xl">Contenuto</div>
</div>

Qui il raggio esterno è 32px. Il bordo è spesso 4px, quindi sulla sua curva interna il raggio scende a 28px. Togli i 12px di padding e il figlio usa 16px.

Esempi pratici

Card, menu e barra di ricerca hanno tutti un raggio esterno di 24px e 8pxdi padding, quindi l'interno corretto è 16px5. Attiva Corretto per confrontarlo con lo stesso componente a 8px.

Card
Context menu
Searchbar

Quando il raggio arriva a zero

Il calcolo ha un limite: se la distanza fra i bordi raggiunge o supera il raggio esterno, non resta spazio per una curva interna concentrica. Il max(…, 0) nella formula tiene conto di questo caso. La specifica CSS3porta a zero i raggi interni che risulterebbero negativi, e l'angolo diventa vivo.

La concentricità, quindi, non richiede che ogni elemento abbia angoli visibilmente arrotondati. Il raggio del figlio dipende dallo spazio che lo separa dal contenitore: assegnargli comunque un valore positivo cambierebbe quella relazione.

Controllare il risultato

Per scegliere il raggio interno, parti da quello esterno e misura tutta la distanza fra le curve, compreso lo spessore del bordo. Sottrai quella distanza e fermati a zero se il risultato è negativo. Poi confronta gli angoli nel componente: negli esempi puoi cambiare il raggio interno e vedere come varia lo spazio rispetto ai lati dritti.

Per approfondire

  1. CSS-Tricks, Careful With Your Nested Border-Radii: le due curve devono avere lo stesso centro. Con un bordo di 5px e un raggio esterno di 25px, l'interno scende a 20px.
  2. Cloud Four, The Math Behind Nesting Rounded Corners: Paul Hebert ricava la formula pensando agli angoli come a cerchi e la traduce in calc().
  3. W3C, CSS Backgrounds and Borders, Rounded Corners: il raggio interno del bordo è quello esterno meno lo spessore, quello del contenuto toglie anche il padding, e un risultato negativo diventa zero.
  4. MDN, border-radius: la sintassi, i valori per i singoli angoli e i raggi ellittici.
  5. 30 seconds of code, Perfect nested border radius in CSS: lo stesso caso degli esempi pratici, 24px fuori e 8px di padding, scritto con variabili CSS.