{
"$type": "site.standard.document",
"description": "Radio groups naturally have cyclical roving tab index, but, I put them into a circle and now it really looks cyclical hehe.",
"path": "/cyclical-radio-group-with-trig-functions-and-grid",
"publishedAt": "2023-03-10T23:44:41.703Z",
"site": "at://did:plc:jnj7wcwuvspxdsipmecmx7rs/site.standard.publication/self",
"tags": [
"blog",
"css"
],
"textContent": "CSS trig functions can do some neat layout stuff, like circles! In this bite size blog post I quickly share how I turned the cyclical roving tab index feature of a radio group, into a circle so it can cycle seamlessly. I'm just inside a radio group usin arrow keys. The gist # Bramus wrote a great post on the new CSS trigonometry functions , and it got me thinking. Those thoughts led to this demo , where I wanted the infinite cycling of focus of a radio group, to tail call itself via a circle layout. < fieldset style = \"--sibling-count: 8\" > < input style = \"--sibling-index: 1\" type = \"radio\" name = \"cyclical-group\" checked> < input style = \"--sibling-index: 2\" type = \"radio\" name = \"cyclical-group\" > < input style = \"--sibling-index: 3\" type = \"radio\" name = \"cyclical-group\" > < input style = \"--sibling-index: 4\" type = \"radio\" name = \"cyclical-group\" > < input style = \"--sibling-index: 5\" type = \"radio\" name = \"cyclical-group\" > < input style = \"--sibling-index: 6\" type = \"radio\" name = \"cyclical-group\" > < input style = \"--sibling-index: 7\" type = \"radio\" name = \"cyclical-group\" > < input style = \"--sibling-index: 8\" type = \"radio\" name = \"cyclical-group\" > </ fieldset > I also used a custom property version of this spec proposal I have open with the CSSWG for sibling-count() and sibling-index() , where an element could know how many siblings it has and which index it currently is. By \"used a version of this proposal\" I mean, I hand wrote the values 😅 fieldset { /* divide circle by total children */ --_offset : calc (360 deg / var (--sibling-count)) ; /* size also used for circle translateX and Y */ --_circle-size : 25 vmin ; inline-size : var (--_circle-size) ; block-size : var (--_circle-size) ; /* 1x1 centered cell */ --_cell-size : 10 vmin ; display : grid ; place-content : center ; grid : var (--_cell-size) / var (--_cell-size) ; /* stack them together in 1 cell */ > * { grid-area : 1/1 ; } } Get used to that nesting syntax!! woot woot! With a grid layout setup with all the radios aligned in the middle, and the radius known of the circle, we can do the math. input { /* take child index * circle fraction offset */ --_angle : calc ( var (--sibling-index) * var (--_offset)) ; /* cos() translateX, sin() translateY */ translate : calc ( cos ( var (--_angle)) * var (--_circle-size)) calc ( sin ( var (--_angle)) * var (--_circle-size)) ; } And that's that, individual transforms making x and y easy to set. Each radio takes it's current index and multiplies it by the ratio in offset, then uses that angle against the circle radius with cos() and sin() . Rad. Try it on Codepen # I used CSS nesting and trig functions, so you'll need Canary with web experiements turns on, for now. See the Pen by Adam Argyle ( @argyleink ) on CodePen .",
"title": "Cyclical keyboard UX with a radio group and CSS trig functions"
}