Skip to content

Custom Gradient

The <HoverTilt /> component comes with a good default glare effect, using my experience in designing tilting cards as a basis.

However, it’s quite possible you may need a custom glare gradient effect, so we expose --hover-tilt-custom-gradient. This lets you replace the default glare look without having to roll your own component from scratch!

You can use this to customise the gradient design to your needs.

The gradient CSS looks something like this;

.hover-tilt-container {
--gradient-x: calc(var(--hover-tilt-x, 0.5) * 100%); /* gradient X position (0% -> 100%) */
--gradient-y: calc(var(--hover-tilt-y, 0.5) * 100%); /* gradient Y position (0% -> 100%) */
}
.hover-tilt {
--hover-tilt-default-gradient: radial-gradient(
farthest-corner circle at var(--gradient-x) var(--gradient-y),
lch(95% 2.7 var(--hover-tilt-glare-hue, 270) / calc(var(--hover-tilt-glare-intensity, 1) * 0.66)) 8%,
lch(88% 5.5 var(--hover-tilt-glare-hue, 270) / calc(var(--hover-tilt-glare-intensity, 1) * 0.5)) 28%,
lch(05% 3.5 var(--hover-tilt-glare-hue, 270) / calc(var(--hover-tilt-glare-intensity, 1) * 0.25)) 90%
);
}
.hover-tilt::before {
/* we look for a custom gradient first, falling back to the default gradient */
background-image: var(--hover-tilt-custom-gradient, var(--hover-tilt-default-gradient));
}

The pointer coordinates are mirrored into CSS via --gradient-x and --gradient-y, to position the gradient wherever the pointer is on the card.

The steps for overriding the built-in dynamic gradient are;

  1. Write your desired gradient code using CSS calc() with var(--gradient-x) / var(--gradient-y). (see below)

  2. Assign it to --hover-tilt-custom-gradient using a CSS class.

Here’s a bunch of custom gradient examples! While I won’t go into detail for each one, I will explain a simple one below, and list out the CSS variables that can be used.

Each card sets a unique --hover-tilt-custom-gradient value. Notice how the glare follows the pointer differently depending on whether the gradient is radial, conic, or directional.

Here’s a breakdown of a simple custom gradient, with each part and how it works.

  1. First we need to call the component and set a glareIntensity value.

    <HoverTilt class="simple-card" glareIntensity="{1}">
    ...
    </HoverTilt>
  2. Then we need to create a CSS selector to target the container of the <HoverTilt /> component.

    :global(.simple-card) {/* ... */}

    We target the container of the <HoverTilt /> component with the :global() selector in Svelte, or the ::part(container) selector in Web Component.

  3. Next we assign the custom gradient to the --hover-tilt-custom-gradient CSS variable.

    :global(.simple-card) {
    --hover-tilt-custom-gradient: /* ... */;
    }

    This variable will be used to override the default gradient.

  4. To make the gradient move around dynamically based on the tilt effect, we use the --gradient-x and --gradient-y variables.

    /***
    CSS radial-gradient syntax:
    radial-gradient( [size/shape] at [horizontal offset] [vertical offset], [color1] [stop1], [color2] [stop2], [colorN] [stopN] );
    ***/
    --hover-tilt-custom-gradient:
    /*** radial-gradient( [size/shape] at [horizontal offset] [vertical offset], [color1] [stop1], [color2] [stop2] ); ***/
    radial-gradient( circle at var(--gradient-x) var(--gradient-y), rgb(255 255 255 / 1) 10%, transparent 70% );
    /*** │ │
    │ └─ gradient-y offset
    └─ gradient-x offset
    ***/

    When the component has no tilt applied (either inactive, or the user has perfect centering of the pointer), then the --gradient-x and --gradient-y variables will be 50%, so a gradient position of 50% 50%.

    But if the user tilts in the negative x direction, then --gradient-x will be 0%, so a gradient position of 0% 50%. Likewise when tilted in the positive x direction, then --gradient-x will be 100%, so a gradient position of 100% 50%.

  5. Lastly we have access to the --hover-tilt-glare-intensity variable, which is the value of the input prop; glareIntensity.

    --hover-tilt-custom-gradient:
    /*** radial-gradient( [size/shape] at [horizontal offset] [vertical offset], [color1] [stop1], [color2] [stop2] ); ***/
    radial-gradient( circle at var(--gradient-x) var(--gradient-y), rgb(255 255 255 / calc(var(--hover-tilt-glare-intensity, 1) * 0.5)) 10%, transparent 70% );
    /*** │ │
    │ └─ multiplied by 0.5
    └─ glare-intensity for color opacity ───┘
    ***/

    So we can use this to control the opacity of the gradient color stops, optionally multiplying the --hover-tilt-glare-intensity value, with calc() by a factor to adjust the intensity. eg: calc(var(--hover-tilt-glare-intensity, 1) * 0.5).

And so the final (basic) custom gradient implementation looks like this;

:global(.simple-card) {
--hover-tilt-custom-gradient: radial-gradient(
circle at var(--gradient-x) var(--gradient-y),
rgb(255 255 255 / calc(var(--hover-tilt-glare-intensity, 1) * 0.5)) 10%,
transparent 70%
);
}

This may seem a little daunting and complex at first, but if you have experience with CSS calc() and var() functions, it should be relatively straightforward.

These variables are available to customise the gradient appearance / position.

They can also be used inside the content slot to customise the way your content reacts to the hover-tilt interactions!

You can set these variables to override the default gradient with your own gradient.

VariableDescription
--hover-tilt-custom-gradientOverride the default glare gradient with your own gradient.

The component will set these variables to control the gradient appearance / position. You may consume these in the --hover-tilt-custom-gradient variable.

The variables are exposed via ::slotted(*) so that they can be picked up by your slotted content to customise the way your content reacts to the hover-tilt interactions!

VariableDescription
--gradient-xDynamic horizontal position (0%-100%) of the gradient focal point.
--gradient-yDynamic vertical position (0%-100%) of the gradient focal point.
--hover-tilt-glare-intensityMirrors the glareIntensity prop; handy for scaling gradient-stop opacities.
--hover-tilt-glare-hueMirrors the glareHue prop; handy for a per-component hue setting.
--hover-tilt-angleReal-time pointer angle in degrees. Can rotate conic/linear gradients with it.
--hover-tilt-from-centerDistance from the center in pixels. Great for intensifying the gradient toward edges.
--hover-tilt-at-edgeCloseness (0–1) to any edge. Useful for edge-effects.

See all the positional variables available in the Options → CSS page.