DEV Community

Cover image for UI Challenge - Elevate CSS masking techniques - Pt2
Emmanuel Mendoza
Emmanuel Mendoza

Posted on

UI Challenge - Elevate CSS masking techniques - Pt2

In this post I will be showing a use case for the Avatar component just built on previous post.

The Grid

Our goal is building a Grid component that will take Avatars with some additional text info as children, to then add some cool video playing in the background. In order to achieve this the following steps will be performed:

  • Create an Avatar Card component that will be using the Avatar component followed by 2 text fields holding the Name and Role info.
  • Putting a couple of Avatar Card components together in a grid.
  • Adding a video that will be playing nicely and quietly in the page background.

While on paper it seems to be quite normal html/css coding, some complications were hit down the road as I couldn't use any background on any Avatar parent element to produce the desired effect.
When coding a web component, I try to maximize the HTML/CSS code but sometimes JS is the cleanest and simplest way to achieve certain functionallity as in this case. I was looking for creating a Grid component where items are centered (just like CSS Grid justify-content: center property does) but after some attempts using CSS only, and keeping in mind that we need to make the Grid responsive and flexible (Grid component is not aware of children element size) I realized that JS will be the best way to go. Once again, I like to keep the code as readable and clean as possible, and that includes CSS code (and here is where using the shape to clip all outside content rathen that creating a new shape - e.g. an square containing an hexagon - and be able to manage the aspect ratio of it take relevance, as the mask container can horizontally grow as much as needed without affecting the shape aspect ratio, so we don't need any extra empty side elements to get the same element growing effect), so if CSS is getting too complicated I tend to reconsider the implementation design but of course, this is just a personal coding style choice.

So, in order to get items sorted in a centered fashion, I created the below component (made it with React TS). Below is the code:

const SideGrowingGrid: React.FC<SideGrowingGridProps> = ({ coverColor = 'white', children }): ReactElement => {
    const [gridRef, { width }] = useElementSize();
    const [itemRef, { width: iWidth }] = useElementSize();
    const childs = ( (children as JSX.Element[]).map ? children : [(children as JSX.Element)] ) as JSX.Element[]; 
    const itemsPerRow : number = iWidth === 0 ? childs.length : iWidth > width ? 1 : Math.floor(width / iWidth);

    return (
        <div className='sgg-container'
            ref={gridRef}>
            {
                ([...Array(Math.ceil(childs.length / itemsPerRow))]).map((e, i) =>  (
                    <div className='sgg-row' key={i}>
                        <div style={{backgroundColor: coverColor, flexGrow: 1}}></div>
                    {      
                        childs.slice(i * itemsPerRow, i * itemsPerRow + itemsPerRow).map((child, j) => (
                            <div key={j} ref={(i === 0 && j === 0) ? itemRef : null}>
                                {child}
                            </div>
                        ))
                    }
                        <div style={{backgroundColor: coverColor, flexGrow: 1}}></div>
                    </div>
                ))
            }
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

Component is quite simple:

  • Use custom hooks to get the Grid size and Grid items size (Note: It assumes all items have the same size).
  • Compute the number of items per Grid row to later create row elements that wraps such children accordingly.
  • Add empty elements in the beginnig and the end of each row that grow and cover the Grid far ends using whatever color it's passed as component property.

That's it, we have our Grid component ready! Nonetheless if you are fine with the items sorting like the CSS Grid - Space Around does, it's quite easy to implement it using CSS only. You can check below Pen implementation and play with it.

Imagination is limitless

Now we have the Grid component, we just need to add a cool background to get most of it. In the company's website we used something subtle (an animated gradient and doodle background), but for this use case, I added a video where visitor can easily tell all Avatars are sharing the same background.

You can take a look to the full implementation here

And in below link you can check the live result:

Avatar Grid

avatar-grid.vercel.app

< UI Challenge - Elevate CSS masking techniques - Pt1

Thank you

That's it, I hope you find this post useful and if you have some cool use case ideas don't hesitate to share them! If you want to connect, you can find me in LinkedIn

Top comments (0)