I’ve published my first npm package. It’s an awesome (but completely useless) react component and the only project that will ever use it is my blog, just for the sake of explaining it. Despite this, I love creating fractals, even if it’s for no use 😉.
About a month ago, during a walk, I was thinking about what new fractal app I could create. Suddenly, an interesting idea came to my head and I rushed to check it out.
There is a fractal geometric shape called Sierpinski’s Carpet. It was first described by Polish mathematician, Wacław Sierpiński in 1916. The construction of the Sierpinski carpet begins with a square. The square is cut into 9 congruent subsquares in a 3-by-3 grid, and the central subsquare is removed. The same procedure is then applied recursively to the remaining 8 subsquares, ad infinitum. Example below:
I’ve implemented it as an interactive clicker and it turned out to be very simple:
(if you can’t see code sandbox below, try to turn off your browser extensions that block tracking - they can interfere with code sandbox embeds)
Here it is how it works - it’s a flexbox component that you have to wrap in a parent element with specified width and height. Every
RecursiveButton component holds its own “clicked” state and initially displays a button. After the button is clicked it begins rendering vertical flexbox instead of a button, with three horizontal flexboxes for three rows of recursively nested, new
RecursiveButton components. All flex child elements (button, rows, column and a gap in the middle) have to have
flex-grow style value set to
1 so they fill all available space evenly.
I had to set button padding and border values to
0 because otherwise when user creates asymmetrical pattern, buttons are being “squished” and move to the side (You can try it - just delete the
r-button class in line 8 in above code sandbox and see how it looks like. It’s quite interesting). After I’ve done it, it turned out that if you set the button’s
0, you lose default browser styles for that button - you have to implement
active pseudo-classes by yourself. To correct that, I’ve added some custom styles to improve the user experience - I wanted it to feel like popping a bubble wrap, so I’ve added gradients to imitate a 3d button effect.
And then yet another idea came to my head - popping bubble wrap can’t be a complete experience without “pop” sound, is it? So I’ve added it too (fortunately it required only 5 new lines of code):
After that I've added some additional features like:
- popping components on button hover (so-called rampage mode)
- undo (it's just reverting state of clicked component back to "unclicked". All it's children are becoming unmounted after that)
- counting how many buttons are on the screen (it can run smoothly even up to 10,000 elements, each of them being separate react component with internal state. As always, fractals are great for performance benchmarking)
You can check out a full version of recursive buttons at https://recursivebuttons.mcalus.dev
Or install the “lite” version as a library with
npm install recursive-buttons. All buttons that are rendered directly in this post are from this library - I bet your site could also use some nice fractal widgets, it would be fancier 😉.