< BACK TO COMPONENTS

How to Create a Liquid Button with HTML, CSS, and JavaScript (Source Code)

Faraz

By Faraz -

Learn how to create a liquid button for your website using HTML, CSS, and JavaScript. Source code included inside.


How to Create a Liquid Button with HTML, CSS, and JavaScript.jpg

Liquid buttons represent an exciting advancement in web design, offering a dynamic and engaging user experience. These buttons incorporate fluid animations and responsive behavior, captivating visitors and enhancing interaction on websites. In this tutorial, we'll explore how to create a liquid button using HTML, CSS, and JavaScript. Join us as we delve into the fascinating world of web development and unleash the potential of liquid buttons to elevate your website's aesthetics and functionality.

Source Code

Step 1 (HTML Code):

To start, create the basic HTML structure for the button. Let's break down the HTML code:


1. <!DOCTYPE html>: This declaration specifies the document type and version of HTML being used.


2. <html lang="en">: The opening tag for the HTML document, indicates that the language used is English.


3. <head>: This section contains meta-information about the document, such as its title, character encoding, and links to external resources like stylesheets and scripts.


  • <meta charset="UTF-8">: Specifies the character encoding for the document, ensuring proper rendering of text.
  • <meta http-equiv="X-UA-Compatible" content="IE=edge">: Provides instructions to Internet Explorer on how to render the webpage.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0">: Sets the viewport properties, ensuring proper scaling on various devices.
  • <title>Liquid Button</title>: Sets the title of the webpage displayed in the browser tab.
  • <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">: Links to an external stylesheet hosted on a CDN (Content Delivery Network) which normalizes CSS styles across different browsers.
  • <link rel="stylesheet" href="styles.css">: Links to another stylesheet named "styles.css" presumably containing additional styles for the webpage.
  • </head>: Closes the head section of the HTML document.

4. <body>: This section contains the visible content of the webpage.


  • <a href="#" class="button">: Defines an anchor (link) element with the class "button". The "#" in the href attribute indicates that the link is a placeholder and doesn't navigate anywhere.
  • <canvas class="button__canvas"></canvas>: Defines a canvas element with the class "button__canvas". This canvas is used for rendering the liquid animation.
  • <span class="button__text">Hover me I am liquid</span>: Defines a span element with the class "button__text" containing the text "Hover me I am liquid". This text will be displayed on the button.
  • </a>: Closes the anchor element.
  • <script src="https://cdn.jsdelivr.net/npm/ola"></script>: Links to an external JavaScript library hosted on a CDN. This library is presumably used for liquid animation.
  • <script src="script.js"></script>: Links to another JavaScript file named "script.js", which contains custom JavaScript code for the webpage.

5. </body>: Closes the body section of the HTML document.


6. </html>: Closes the HTML document.

Step 2 (CSS Code):

Style the button to achieve the liquid effect. Let's break down the CSS code:


1. body: Styles applied to the body element of the webpage.


  • display: flex;: Sets the display property to flex, allowing the flexible layout of child elements.
  • justify-content: center;: Horizontally centers the content within the body.
  • align-items: center;: Vertically centers the content within the body.
  • min-height: 100vh;: Sets the minimum height of the body to 100% of the viewport height, ensuring the content fills the screen.
  • background: #eef;: Sets the background color of the body to a light shade of blue (#eef).

2. .w-100: Styles applied to elements with the class "w-100".


  • width: 100%;: Sets the width of the element to 100%.
  • height: 20px;: Sets the height of the element to 20 pixels.
  • position: relative;: Sets the positioning context to relative for child elements.

3. .button: Styles applied to elements with the class "button".


  • position: relative;: Sets the positioning context to relative for child elements.
  • padding: 1.6em 2.8em;: Sets the padding of the button to 1.6em (top and bottom) and 2.8em (left and right).
  • text-decoration: none;: Removes the default underline decoration from the text within the button.

4. .button__canvas: Styles applied to elements with the class "button__canvas".


  • --offset: 32px;: Defines a CSS custom property named "--offset" with a value of 32 pixels.
  • position: absolute;: Positions the element absolutely within its containing element.
  • top: calc(var(--offset) * -1);: Positions the element at the top by subtracting the offset value.
  • left: calc(var(--offset) * -1);: Positions the element at the left by subtracting the offset value.
  • width: calc(100% + var(--offset) * 2);: Sets the width of the canvas to the width of its container plus twice the offset.
  • height: calc(100% + var(--offset) * 2);: Sets the height of the canvas to the height of its container plus twice the offset.
  • transition: opacity 2s ease;: Applies a transition effect to the opacity property over 2 seconds with ease timing function.

5. .button__text: Styles applied to elements with the class "button__text".


  • position: relative;: Sets the positioning context to relative for child elements.
  • color: white;: Sets the text color to white.
  • font-weight: bold;: Sets the font weight to bold.
  • letter-spacing: 0.02em;: Sets the letter spacing to 0.02em.
  • pointer-events: none;: Disables pointer events on the text, allowing clicks to pass through to underlying elements.

6. .button:hover .button__canvas: Styles applied to the button__canvas element when the button is hovered.


  • opacity: 0.85;: Sets the opacity of the canvas to 0.85 when the button hovers.
  • transition: opacity 0.2s ease;: Applies a transition effect to the opacity property over 0.2 seconds with ease timing function.

7. .button:active .button__canvas: Styles applied to the button__canvas element when the button is active (being clicked).


  • opacity: 1;: Sets the opacity of the canvas to 1 when the button is active.
  • transition: none;: Removes any transition effect on the opacity property.
body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background: #eef;
}

.w-100 {
  width: 100%;
  height: 20px;
  position: relative;
}

.button {
  position: relative;
  padding: 1.6em 2.8em;
  text-decoration: none;
}
.button__canvas {
  --offset: 32px;
  position: absolute;
  top: calc(var(--offset) * -1);
  left: calc(var(--offset) * -1);
  width: calc(100% + var(--offset) * 2);
  height: calc(100% + var(--offset) * 2);
  transition: opacity 2s ease;
}
.button__text {
  position: relative;
  color: white;
  font-weight: bold;
  letter-spacing: 0.02em;
  pointer-events: none;
}
.button:hover .button__canvas {
  opacity: 0.85;
  transition: opacity 0.2s ease;
}
.button:active .button__canvas {
  opacity: 1;
  transition: none;
} 

Step 3 (JavaScript Code):

Implement JavaScript to add interactivity to the button. Use event listeners to detect mouse movements and modify button properties accordingly.


Let's break down the code step by step:


1. The code starts by selecting all elements with the class .button using document.querySelectorAll('.button').


2. It iterates over each selected element using forEach.


3. Inside the loop, it finds the canvas element with the class .button__canvas within each button element and gets its 2D rendering context (ctx).


4. It sets up some constants such as offset, background color, and foreground color for the canvas.


5. It initializes an empty array points and a variable position.


6. It creates a new instance of an object named Ola with a value property initialized to offset. It seems like Ola is a custom class or library being used for animation or value manipulation.


7. It defines a function size() responsible for setting the size of the canvas, initializing the position, and calculating points array based on the canvas dimensions.


8. The reset() function clears the canvas with the background color.


9. The draw() function fills the canvas with the foreground color based on the points array.


10. The attract() function calculates the attraction point for each point based on its distance from the center position.


11. The loop() function is the main animation loop which clears the canvas, draws the shape, and requests the next animation frame.


12. It sets up event handlers for window resize, mouse move, mouse enter, and mouse leave events on the canvas.


13. Inside the event handlers, it updates the position and distance properties accordingly.


14. Finally, it starts the animation loop by calling loop().

document.querySelectorAll('.button').forEach(elem => {

  const canvas = elem.querySelector('.button__canvas');
  const ctx = canvas.getContext('2d');

  const offset = 32;
  const background = '#eef';
  const foreground = '#7551e9';

  let points = [];
  let position;

  const distance = new Ola({
    value: offset });


  const size = () => {

    canvas.width = canvas.getBoundingClientRect().width;
    canvas.height = canvas.getBoundingClientRect().height;

    position = new Ola({
      x: canvas.width / 2,
      y: canvas.height / 2 });


    const pixelsWidth = canvas.width - offset * 2;
    const pixelsHeight = canvas.height - offset * 2;

    const leftTop = [offset, offset];
    const rightTop = [canvas.width - offset, offset];
    const rightBottom = [canvas.width - offset, canvas.height - offset];
    const leftBottom = [offset, canvas.height - offset];

    points = [];

    Array(pixelsWidth).fill().forEach((_, index) => {
      points.push([
      leftTop[0] + index,
      leftTop[1]]);

    });

    Array(pixelsHeight).fill().forEach((_, index) => {
      points.push([
      rightTop[0],
      rightTop[1] + index]);

    });

    Array(pixelsWidth).fill().forEach((_, index) => {
      points.push([
      rightBottom[0] - index,
      rightBottom[1]]);

    });

    Array(pixelsHeight).fill().forEach((_, index) => {
      points.push([
      leftBottom[0],
      leftBottom[1] - index]);

    });

  };

  size();

  const reset = () => {

    ctx.fillStyle = background;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

  };

  const draw = () => {

    ctx.fillStyle = foreground;
    ctx.beginPath();

    points.forEach((point, index) => {

      const [vx, vy] = attract(point);

      if (index === 0) ctx.moveTo(vx, vy);else
      ctx.lineTo(vx, vy);

    });

    ctx.closePath();
    ctx.fill();

  };

  const attract = point => {

    const [x, y] = point;

    const dx = x - position.x;
    const dy = y - position.y;

    const dist = Math.sqrt(dx * dx + dy * dy);
    const dist2 = Math.max(1, dist);

    const d = Math.min(dist2, Math.max(12, dist2 / 4 - dist2));
    const D = dist2 * distance.value;

    return [
    x + d / D * (position.x - x),
    y + d / D * (position.y - y)];


  };

  const loop = () => {
    reset();
    draw();
    requestAnimationFrame(loop);
  };

  window.onresize = size;

  canvas.onmousemove = e => {

    position.set({
      x: e.clientX - e.target.getBoundingClientRect().left,
      y: e.clientY - e.target.getBoundingClientRect().top },
    200);

  };

  canvas.onmouseenter = () => {

    distance.set({
      value: 1 },
    200);

  };

  canvas.onmouseleave = () => {

    position.set({
      x: canvas.width / 2,
      y: canvas.height / 2 },
    2000);

    distance.set({
      value: offset },
    12000);

  };

  loop();

});

Final Output:

How to Create a Liquid Button with HTML, CSS, and JavaScript.gif

Conclusion:

Congratulations! You've successfully created a stunning liquid button using HTML, CSS, and JavaScript. Experiment with different properties and animations to customize it further and enhance user engagement on your website.


Code by: Ivan Grozdic

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee.

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post