Flexible Border Element

Flexible Border Element

# css# frontend# tailwindcss# learning
Flexible Border ElementLisa Cee

I recently transitioned from full stack to front end engineer. Front end is what inspired me to...

I recently transitioned from full stack to front end engineer. Front end is what inspired me to become an engineer and returning to a front end focus has reinvigorated my desire to play with code in my free time. I picked a project on Frontend Mentor and have been building it out on the weekends.

Here is what I am building:
A social media dashboard with each card representing the data for a specific service.

It was going really well; I was building out components, implementing theming and familiarizing myself with Tailwind when I got stumped by the card border.

Border Issues

I already knew that it could be challenging working linear-gradient borders, so I decided to wait on the Instagram card and focus on the solid color borders. It was easy to add a top border to a card with a border-radius, but it didn’t look like the design. The border had a curve on the corner that I didn’t like.
A social media card with rounded corners. The red border on the top is rounded and curves slightly in at the corners.

<div className="rounded-lg border-t-4 border-red-700 flex flex-col items-center gap-6 bg-card py-6 w-[300px]"
    >
    {/* Card content */}
</div>
Enter fullscreen mode Exit fullscreen mode

Rather than stalling my progress by figuring this out, I opted to move on to the Instagram border which ended up providing a solution for both the curved border corners and the gradient border.

Gradient Border

To create the gradient border for the Instagram card, I started with some conditionally logic. If the component was the Instagram card, then conditionally render either a border or a border-image.

An Instagram social media card. It has rounded corners on the bottom. There is a multi-color border on top that does not have rounded corners.

<div 
     className={`rounded-lg border-t-4 ${!isInstagram ? 'border-red-700' : ''} flex flex-col items-center gap-6 bg-card py-6 w-[300px] md:p-6 md:w-full cursor-pointer`}
     style={
        isInstagram
          ? {
          borderRadius: '8px',
          borderImage:
                'linear-gradient(to right, hsl(37, 97%, 70%), hsl(5, 77%, 71%), hsl(329, 70%, 58%)) 1',
            }
          : undefined
      }
>
       {/* Card content */}
</div>
Enter fullscreen mode Exit fullscreen mode

This worked to a point, but I didn't love it. First, I didn’t like the complexity of adding a border for some cards and a border-image to others. I also didn’t like using the inline style tag. Finally, and most importantly, a border-image does not work with border-radius. That was a deal breaker.

The Aha! Moment

As I searched for a solution, I learned that there are a lot of ways to solve for this issue. The cleanest way that I found was to create a css class for the border with a relative position. Then I created a pseudo element using ::before to create an absolutely positioned border with a border radius.

<div className={`rounded-lg  ${!isInstagram ? 'service-border' : 'border-red-700 border-t-4' } flex flex-col items-center gap-6 bg-card py-6 w-[300px] md:p-6 md:w-full cursor-pointer`}
>
     {/* Card content */}
</div>

{/* CSS */}
.service-border {
  position: relative;
}

.service-border:before {
  content: '';
  position: absolute;
  top: -4px;
  left: 0;
  right: 0;
  height: 4px;
  border-radius: 0.5rem 0.5rem 0 0;
  background: linear-gradient(to right, hsl(37, 97%, 70%), hsl(5, 77%, 71%), hsl(329, 70%, 58%));
}
Enter fullscreen mode Exit fullscreen mode

That is where I had the aha moment and discovered that I could solve both of my issues using a pseudo-element. I could have a gradient border with a radius and solve the curved corner issue with the solid-color borders.

Two social media cards side by side. The one on the left has a solid red border on the top and it curves in slightly at the corners. The one on the right has a gradient border at the top and only curves at the corner, leaving a straight line where it meets the card.

Since I was already going to be using some vanilla CSS, I opted to add a dynamic border class based on the service name.

<div className={`rounded-b-lg service-border border-${serviceName} flex flex-col items-center gap-6 bg-card py-6 w-[300px] md:p-6 md:w-full cursor-pointer`}
>
     {/* Card content */}
</div>

{/* CSS */}
.service-border {
  position: relative;
}

.service-border:before {
  content: '';
  position: absolute;
  top: -4px;
  left: 0;
  right: 0;
  height: 4px;
  border-radius: 0.5rem 0.5rem 0 0;
}

.border-facebook::before {
  background: hsl(var(--facebook-border));
}

.border-twitter::before {
  background: hsl(var(--twitter-border));
}

.border-youtube::before {
  background: hsl(var(--youtube-border))
}

.border-instagram::before {
  background: linear-gradient(to right, hsl(37, 97%, 70%), hsl(5, 77%, 71%), hsl(329, 70%, 58%));
}
Enter fullscreen mode Exit fullscreen mode

4 social media cards with various color borders. The all have nicely rounded corners and a flat-based border on the top.

It is still a work in progress, but I was pleasantly surprised by discovering this solution that worked well for both of my border-related challenges. You can check out the WIP project on my GitHub. I'd love to hear your thoughts and your go-to solutions on how to handle CSS border gotchas.

TL;DR

You can create a more flexible border by creating an absolutely-positioned pseudo-element. It provides a nice, flat border, can handle both solid colors and gradients and can accommodate a border-radius.