Rounded rect with transparent background and gradient border

Viewed 1198

I need to make a rectangle with the following things in mind:

  1. transparent white background (80%)
  2. gradient border (different colors that come from the backend, 1px wide)
  3. can scale according to text length

Like this

I've tried using SVG and got it working except point 3.

My attempt now is to use 3 svgs (one for the left/right half circle and one for the middle part and position them absolutely but i can't get it to work just yet.

enter image description here

The middle part shouldn't scale to 100% height but im not familiar enough with svg scaling options.

Im using React and Glamor but that shouldnt matter for this. (snippet doesnt work because of dependencies, but you should get the issue)

import React from 'react';
import ReactDOM from 'react-dom';
import { css, style, after } from 'glamor';

const SectionTag = ({ className, name, url, height, borderWidth, fontSize, theme, fillColor }) => {
  const styles = {
    main: {
      padding: 0,
      display: 'block',
    },
    inline: style({
      display: 'inline-block',
      verticalAlign: 'top',
    }),
    textWrapper: style({
      position: 'relative'
    }),
    background: style({
      position: 'absolute',
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
      width: '100%',
    }),
    text: css({
      zIndex: 1,
      position: 'relative',
      color: theme.accentColor,
      fontSize: fontSize,
      lineHeight: 1,
      textTransform: 'uppercase',
      padding: '8px 1px',
      height,
      margin: 0,
    }),
  };
  return (
    <div className={css(className, styles.main)}>
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width={height / 2}
        height={height}
        viewBox={`0 0 ${height / 2} ${height}`}
        className={styles.inline}
      >
        <rect rx={height / 2} ry={height / 2} x={borderWidth / 2} y={borderWidth / 2}
              width={(height * 2) - (borderWidth)}
              height={height - (borderWidth)}
              style={{
                fill: fillColor,
                stroke: `url(#gradient-${name.replace(/ /g, '-').toLowerCase()})`,
                strokeWidth: borderWidth
              }} />
      </svg>
      <div className={css(styles.textWrapper, styles.inline)}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          height={height}
          viewBox={`0 0 ${height - 4} ${height}`}
          className={css(styles.background)}
          preserveAspectRatio="xMidYMin slice"
        >
          <linearGradient id={`gradient-${name.replace(/ /g, '-').toLowerCase()}`}>
            <stop offset="0" style={{ stopColor: theme.leftColor }} />
            <stop offset="1" style={{ stopColor: theme.rightColor }} />
          </linearGradient>
          <rect
            x={-borderWidth}
            y={0}
            width={height - (borderWidth * 2)}
            height={height - (borderWidth * 2)}
            style={{
              fill: fillColor,
              stroke: `url(#gradient-${name.replace(/ /g, '-').toLowerCase()})`,
              strokeWidth: borderWidth,
              vectorEffect: 'non-scaling-stroke',
              height: height,
              top: 0,
              padding: 0,
              margin: 0,
            }} />
        </svg>
        <p
          height={height}
          className={css(styles.text, styles.inline)}
        >
          {name}
        </p>
      </div>
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width={height / 2}
        height={height}
        viewBox={`0 0 ${height / 2} ${height}`}
        className={styles.inline}
      >
        <rect rx={height / 2} ry={height / 2} x={-(height * 1.5)} y={borderWidth / 2}
              width={(height * 2) - (borderWidth)}
              height={height - (borderWidth)}
              style={{
                fill: fillColor,
                stroke: `url(#gradient-${name.replace(/ /g, '-').toLowerCase()})`,
                strokeWidth: borderWidth
              }} />
      </svg>
    </div>
  );
};

SectionTag.propTypes = {};
SectionTag.defaultProps = {
  name: 'default',
  height: 29,
  borderWidth: 1,
  fontSize: 10,
  fillColor: 'rgba(255, 255, 255, .8)',
  theme: {
    leftColor: 'rgba(255, 188, 0, 0.31)',
    rightColor: '#ff0000',
    accentColor: '#f9811b'
  }
};

const mountNode = document.querySelector('.el');
ReactDOM.render(<SectionTag name="Jane" />, mountNode);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="el"></div>

3 Answers
Related