Skip to content

Mesh Gradient

<quiet-mesh-gradient> experimental since 1.0

Generates beautiful mesh gradients with customizable colors and complexity.

A Purrfect Mesh

Text colors automatically adjust to ensure readability

Random seed
Copy Component HTML Copy Gradient CSS
<div id="mesh__overview">
  <!-- This generates a mesh gradient -->
  <quiet-mesh-gradient 
    style="--gradient-color: #f97316;"
    complexity="3" 
    seed="75"
    brightness="40"
  >
    <h2>A Purrfect Mesh</h2>
    <p>Text colors automatically adjust to ensure readability</p>
  </quiet-mesh-gradient>

  <!-- Everything below is code for the demo -->
  <div class="row">
    <quiet-color-input 
      label="Base color"
      value="#f97316"
      swatches="
        #09090b; #71717a; #ef4444; #f97316; 
        #f59e0b; #eab308; #84cc16; #22c55e; 
        #10b981; #14b8a6; #06b6d4; #3b82f6; 
        #6366f1; #a855f7; #d946ef; #ec4899
      "  
      with-input
      with-eye-dropper
      with-clear
    ></quiet-color-input>

    <quiet-button>
      <quiet-icon slot="start" name="reload"></quiet-icon>
      Random seed
    </quiet-button>
  </div>

  <quiet-slider
    label="Complexity"
    min="1"
    max="8"
    value="3"
    with-markers
    with-tooltip
  ></quiet-slider>

  <quiet-slider
    label="Brightness"
    min="-100"
    max="100"
    value="40"
    with-tooltip
  ></quiet-slider>

  <div class="row">
    <quiet-copy class="copy-html">
      <quiet-button>
        <quiet-icon slot="start" name="file-type-html"></quiet-icon>
        Copy Component HTML
      </quiet-button>
    </quiet-copy>

    <quiet-copy class="copy-css">
      <quiet-button>
        <quiet-icon slot="start" name="file-type-css"></quiet-icon>
        Copy Gradient CSS
      </quiet-button>
    </quiet-copy>
  </div>
</div>

<script type="module">
  import { allDefined } from '/dist/quiet.js';

  const container = document.getElementById('mesh__overview');
  const meshGradient = container.querySelector('quiet-mesh-gradient');
  const colorInput = container.querySelector('quiet-color-input');
  const complexitySlider = container.querySelector('quiet-slider[label="Complexity"]');
  const brightnessSlider = container.querySelector('quiet-slider[label="Brightness"]');
  const seedButton = container.querySelector('quiet-button');
  const copyHtmlButton = container.querySelector('.copy-html');
  const copyCssButton = container.querySelector('.copy-css');  

  // Track current values
  let currentValues = {
    color: '#f97316',
    complexity: 3,
    seed: 75,
    brightness: 40
  };

  colorInput.addEventListener('input', () => {
    currentValues.color = colorInput.value;
    meshGradient.style.setProperty('--gradient-color', currentValues.color);
    updateCopyData();
  });

  complexitySlider.addEventListener('input', () => {
    currentValues.complexity = complexitySlider.value;
    meshGradient.complexity = currentValues.complexity;
    updateCopyData();
  });

  brightnessSlider.addEventListener('input', () => {
    currentValues.brightness = brightnessSlider.value;
    meshGradient.brightness = currentValues.brightness;
    updateCopyData();
  });

  seedButton.addEventListener('click', () => {
    currentValues.seed = Math.floor(Math.random() * 1000) + 1;
    meshGradient.seed = currentValues.seed;
    updateCopyData();
  });
  
  // Update the copy button's data
  function updateCopyData() {
    copyHtmlButton.data = `
<quiet-mesh-gradient
  style="--gradient-color: ${currentValues.color};"
  complexity="${currentValues.complexity}"
  seed="${currentValues.seed}"
  brightness="${currentValues.brightness}"
>
  <!-- Your content here -->
</quiet-mesh-gradient>
  `.trim();

    // Get CSS from the component's rendered styles
    const textColor = meshGradient.style.getPropertyValue('--optimal-text-color') || 'inherit';
    const gradientEl = meshGradient.shadowRoot.querySelector('#gradient');
    const gradientStyle = gradientEl.getAttribute('style') || '';    
    const cssProperties = gradientStyle.trim().replace(/;\s*/g, ';\n  ').replace(/;\n  $/, ';');

    copyCssButton.data = `
.mesh-gradient {
  color: ${textColor};
  ${cssProperties}
}
    `.trim();
  }
  
  await allDefined();

  // Initialize copy data
  updateCopyData();
  </script>

<style>
  #mesh__overview {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;

    quiet-mesh-gradient {
      height: 300px;
      padding: 2rem;
    }

    quiet-color-input {
      flex: 1;
    }

    .row {
      display: flex;
      flex-wrap: wrap;
      gap: 1rem;
      align-items: end;
    }
  }
</style>

This component is convenient, but it adds a lot more bytes than the gradient's CSS alone. If you don't need to generate mesh gradients dynamically, you'll get better performance using this generator and copying the gradient's CSS directly into your project.

Examples Jump to heading

Setting the color Jump to heading

Set the --gradient-color custom property to control the mesh gradient's color.

The text color will automatically adjust to white or black based on the gradient. You can override this behavior by setting the color property in your CSS. Within the host element, the --optimal-text-color custom property can be used to access this color.

Light backgrounds get dark text Dark background get light text
<quiet-mesh-gradient
  style="--gradient-color: #fad5ff; height: 250px;"
  complexity="3"
  seed="24"
  brightness="40"
>
  Light backgrounds get dark text
</quiet-mesh-gradient>

<quiet-mesh-gradient
  style="--gradient-color: #561161; height: 250px;"
  complexity="3"
  seed="75"
  brightness="40"
>
  Dark background get light text
</quiet-mesh-gradient>

Providing Content Jump to heading

Content slotted into the mesh gradient will be centered by default. You can target the ::part(content) selector in your CSS to change how text is displayed.

Beautiful mesh gradient

Text is automatically colored based on the background

<quiet-mesh-gradient
  style="--gradient-color: #5290f6; height: 250px;"
  complexity="8"
  seed="870"
  brightness="24"
>
  <h2>Beautiful mesh gradient</h2>
  <p>Text is automatically colored based on the background</p>
</quiet-mesh-gradient>

Brightness Control Jump to heading

Adjust the brightness from -100 (darker) to +100 (lighter). Positive values create a tinted effect (lighter and slightly desaturated), while negative values create a shaded effect (darker while maintaining richness):

Lighter (+75)

Original

Darker (-75)

<quiet-mesh-gradient style="--gradient-color: #3b82f6; height: 250px;" brightness="75" seed="100">
  <p>Lighter (+75)</p>
</quiet-mesh-gradient>
<quiet-mesh-gradient style="--gradient-color: #3b82f6; height: 250px;" brightness="0" seed="100">
  <p>Original</p>
</quiet-mesh-gradient>
<quiet-mesh-gradient style="--gradient-color: #3b82f6; height: 250px;" brightness="-75" seed="100">
  <p>Darker (-75)</p>
</quiet-mesh-gradient>

Providing a seed Jump to heading

A random gradient is generated by default, but you can set the seed attribute to any number to generate the same gradient every time.

<quiet-mesh-gradient seed="42" style="--gradient-color: #9B59B6; height: 250px;"></quiet-mesh-gradient>
<quiet-mesh-gradient seed="42" style="--gradient-color: #9B59B6; height: 250px;"></quiet-mesh-gradient>
<!-- These two will look identical -->

Complexity Jump to heading

Control the number of gradient layers with the complexity property:

<quiet-mesh-gradient complexity="2" style="--gradient-color: #FF6B6B; height: 250px;" seed="100"></quiet-mesh-gradient>
<quiet-mesh-gradient complexity="6" style="--gradient-color: #FF6B6B; height: 250px;" seed="100"></quiet-mesh-gradient>
<quiet-mesh-gradient complexity="8" style="--gradient-color: #FF6B6B; height: 250px;" seed="100"></quiet-mesh-gradient>

API Jump to heading

Importing Jump to heading

The autoloader is the recommended way to import components but, if you prefer to do it manually, the following code snippets will be helpful.

CDN npm

To manually import <quiet-mesh-gradient> from the CDN, use the following code.

import 'https://cdn.jsdelivr.net/npm/@quietui/quiet-browser@1.0.0/dist/components/mesh-gradient/mesh-gradient.js';

To manually import <quiet-mesh-gradient> from npm, use the following code.

import '@quietui/quiet/dist/components/mesh-gradient/mesh-gradient.js';

Slots Jump to heading

Mesh Gradient supports the following slots. Learn more about using slots

Name Description
(default) Content to display over the gradient.

Properties Jump to heading

Mesh Gradient has the following properties that can be set with corresponding attributes. In many cases, the attribute's name is the same as the property's name. If an attribute is different, it will be displayed after the property. Learn more about attributes and properties

Property / Attribute Description Reflects Type Default
complexity The number of gradient layers to generate. number 4
seed A seed value for consistent gradient generation. If not provided, the gradient will be random. number
undefined
brightness Adjusts the brightness of the gradient from -100 (darker) to +100 (lighter). number 0

Methods Jump to heading

Mesh Gradient supports the following methods. You can obtain a reference to the element and call them like functions in JavaScript. Learn more about methods

Name Description Arguments
regenerate() Regenerates the gradient. Useful for creating new random gradients programmatically.

CSS custom properties Jump to heading

Mesh Gradient supports the following CSS custom properties. You can style them like any other CSS property. Learn more about CSS custom properties

Name Description Default
--gradient-color The base color for the gradient. Accepts any valid CSS color format, but does not accept custom properties, e.g. var(--my-color).
--optimal-text-color A readonly custom property that maps to the optimal text color (black or white) based on the gradient's base color.

CSS parts Jump to heading

Mesh Gradient exposes internal elements that can be styled with CSS using the selectors shown below. Learn more about CSS parts

Name Description CSS selector
gradient The gradient container element for styling the gradient layer. ::part(gradient)
content The content container element for styling the content layer. ::part(content)
Search this website Toggle dark mode Get the code on GitHub Follow @quietui.org on Bluesky Follow @quiet_ui on X

    No results found