underfrankenwood
underfrankenwood

Reputation: 893

How to use @property in styled components?

I want to use animation in my app, but it requires @property function from SCSS:

@property --border-angle {
  syntax: "<angle>";
  inherits: true;
  initial-value: 0turn;
}

Is there a way to do it in styled-components?

The whole code for animation is on: https://codepen.io/shshaw/pen/RwJwJJx

Or how to re-write this function so it does not have to use property function?

Upvotes: 0

Views: 780

Answers (1)

John Li
John Li

Reputation: 7447

The posted code does seem to work with styled-components as I tested, although it seems that the browser support for @property is still limited, such as it works for Chrome but not currently for Firefox, therefore the gradient animation will not play on it.

I tried to create an alternative version of the posted code without the use of @property, which runs on Firefox as well. In case if it could be useful, here is a demo on: stackblitz (code included at the end of the answer).

The original posted code was tested with below example on: stackblitz (gradient animation by @property not currently supported by Firefox).

// Styled components
const Container = styled.div`
  height: 100%;
  background: #223;
  display: grid;
  place-items: center;
`;

const Box = styled.div`
  --border-size: 3px;
  --border-angle: 0turn;
  width: 60vmin;
  height: 50vmin;
  background-image: conic-gradient(
      from var(--border-angle),
      #213,
      #112 50%,
      #213
    ),
    conic-gradient(from var(--border-angle), transparent 20%, #08f, #f03);
  background-size: calc(100% - (var(--border-size) * 2))
      calc(100% - (var(--border-size) * 2)),
    cover;
  background-position: center center;
  background-repeat: no-repeat;
  animation: bg-spin 3s linear infinite;
  @keyframes bg-spin {
    to {
      --border-angle: 1turn;
    }
  }
  &:hover {
    animation-play-state: paused;
  }
  @property --border-angle {
    syntax: "<angle>";
    inherits: true;
    initial-value: 0turn;
  }
`;

export default function App() {
  return (
    <Container>
      <Box></Box>
    </Container>
  );
}

Below is the alternative version without @property for comparison, it used pseudo-element and added a child div to recreate the animation in styled-components.

Live demo on: stackblitz (should also work for Firefox).

// Styled components
const Container = styled.div`
  min-height: 100vh;
  background: #223;
  display: grid;
  place-items: center;
`;

const Box = styled.div`
  width: 60vmin;
  height: 50vmin;
  position: relative;
  overflow: hidden;
  &::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: conic-gradient(from 0turn, transparent 20%, #08f, #f03);
    animation: fallback-spin 3s linear infinite;
  }
  @keyframes fallback-spin {
    to {
      transform: scale(1000%) rotate(1turn);
    }
  }
  &:hover::before {
    animation-play-state: paused;
  }
  &:hover > div::before {
    animation-play-state: paused;
  }
`;

const Fallback = styled.div`
  position: absolute;
  inset: 3px;
  overflow: hidden;
  background-color: pink;
  &::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: conic-gradient(from 0turn, #213, #112 50%, #213);
    animation: fallback-spin 3s linear infinite;
  }
  @keyframes fallback-spin {
    to {
      transform: scale(1000%) rotate(1turn);
    }
  }
`;

export default function App() {
  return (
    <Container>
      <Box>
        <Fallback></Fallback>
      </Box>
    </Container>
  );
}

@property is newer but standard CSS, by the way. More background about @property on MDN.

Upvotes: 1

Related Questions