Master Frontend to Backend eBook Banner
CSS Custom Properties and Houdini
CSS Custom Properties and Houdini

The Future of CSS: Exploring CSS Custom Properties and Houdini

A collection of APIs known as CSS Houdini enables developers to control the styling and layout operations carried out by a browser, thereby enhancing the low-level capabilities of CSS.

CSS Houdini allows developers to change the styling dynamically with the help of JavaScript. Therefore, instead of updating styles through JavaScript, developers can write CSS code that the browser can interpret.

The Future of CSS: Exploring CSS Custom Properties and Houdini

Since it was first introduced in the mid-1990s, CSS (Cascading Style Sheets) has advanced significantly. It has changed over time to match the requirements of modern web development and design.

Because of two significant developmentsā€”CSS Custom Properties and CSS Houdiniā€”CSS is currently on the verge of a new age. In this post, we’ll examine these developments and examine how they’re influencing web layout in the future.

CSS Houdini: The Magic of Extensibility

Houdini helps in building dynamic and unique animating websites which is not possible by using the traditional css. CSS Houdini changes the website styling dynamically with timing with the help of JavaScript. The most notable result is its capacity to make it easier to create unique effects and animations that were previously unachievable with conventional CSS.

The Houdini APIs have various kinds of modules that help in creating different styling functions. Some of them are discussed below:

  1. Paint Worklet: This module enables developers to construct custom paint functions that let them draw complex images and shapes on a website.
  2. Animation Worklet: Using this module, developers can create custom animations that apply to any element on a webpage.
  3. Typed OM: This module gives developers access to the CSS object model using a typed interface, making it easier and more effective to work with CSS properties.
  4. Layout Worklet: With the help of this module, developers can make custom layout algorithms that help with the positioning and scaling of items on a webpage.

In CSS Houdini APIs are divided into two types: High-level and low-level APIs. These APIs are made to give developers various degrees of flexibility and capability when utilizing Houdini’s skills to enhance and modify the CSS rendering engine in web browsers.

1. High-level APIs:

Houdini’s high-level APIs are made to be more developer-friendly and abstracted so that developers can do typical styling and layout chores without having to get too deep into the specifics of the rendering engine.

Paint API:

The high-level APIs’ Paint API enables developers to create unique background and border effects, effectively replacing or improving standard CSS properties like background-image and border-image. With the help of this API, programmers can create their own painting algorithms and utilize them directly in CSS properties.

To generate gradients, patterns, or intricate textures for backgrounds, for example, you may design a unique paint worklet.

Layout API:

It’s very helpful for designing intricate and unusual layouts that can’t be done with just conventional CSS. To control the positioning and scaling of elements within a container, developers can register layout worklets.

A layout worklet could be made, for instance, to implement a Masonry-style layout, which arranges objects in a grid with different heights.

2. Low-Level APIs:

Houdini’s low-level APIs provide developers with greater precise control. They are made for people who need specific access to the rendering pipeline so they may control styles and rendering at a more fundamental level.

Property API (Properties and Values API):

Developers can define unique CSS attributes and values using the low-level attributes and Values API. This API has a wide range of effects on the styling or layout of an element.

An example of a custom CSS attribute that may be defined and dynamically updated using JavaScript is the spacing between elements.

Animation API (Worklet Animation API):

With the help of this API, developers can produce animations with distinct behaviors and effects that are not possible with conventional CSS animations. For example, you can design a unique animation timing algorithm that clones motion based on real physics.

CSS Houdini Working

HTML Code:

A user interface made of HTML code allows users to choose from various drawing patterns (such as lines, triangles, or the Joy Division logo), change the pattern’s size with a slider, and includes a login form on a card.
A JavaScript component of the code additionally provides a custom paint module for creating patterns if CSS Paint Worklet support is found. In addition, dependent on the value of the slider, an event listener modifies the size of the card. A credit link to the code’s original location is included at the end.

<div class="wrapper" id="app">
  <input type="radio" name="drawing" value="lines" id="lines"/>
	<label for="lines" class="label">Lines</label>
	
	<input type="radio" name="drawing" value="triangles" id="triangles"/>
	<label for="triangles" class="label">Triangles</label>

	<input type="radio" name="drawing" value="joyDivision"  id="joyDivision"/>
	<label for="joyDivision" class="label">JoyDivision</label>
	
	<input type="range" name="size" id="size" class="slider" min="26" max="200" value="50"/>
	
	<div class="card">
		<form class="form" onsubmit="event.preventDefault();">
      <input type="text" placeholder="username"/>
      <input type="password" placeholder="password"/>
      <button>login</button>
    </form>
	</div>
</div>

<span class="credit">Code for pattern generation from <a href="https://generativeartistry.com/">generativeartistry.com</a> </span>

<script>
  if (CSS.paintWorklet) {
    CSS.paintWorklet.addModule('/lisilinhart/pen/LYEJWQQ.js');
  } else {
    document.body.classList.add('warning');
  }
	
	document.addEventListener("DOMContentLoaded",function(){
		let el = document.querySelector('#size');
		el.addEventListener('change', function(e) {
			let card = document.querySelector('.card');
			let value = e.target.value   
			card.style.setProperty('--size', value)
		});
	});

	
</script> 
The Future of CSS: Exploring CSS Custom Properties and Houdini

CSS Code:

ADVERTISEMENT

A combination of HTML and CSS produces a user interface for choosing and viewing various drawing patterns, altering their size, and including a login form inside a card. Background patterns created with the CSS Paint API (Houdini) are among the elements whose look and behavior are controlled by CSS custom properties (variables). Users can choose from a variety of drawing patterns, such as lines, triangles, or the Joy Division style, and then use a slider to change the pattern’s size. By displaying a warning message if the browser is unable to support the CSS Paint API, the code also offers graceful degradation. Additionally, a credit link to the code’s original location is provided.

ADVERTISEMENT

:root {
	--c-primary: #E0AF53;
	--c-secondary: #d1274b;
	--c-light: #f8f8f8;
}

// CSS Houdini
.card {
	background: var(--c-light);
	background-image: paint(generative);
	// Types: lines,joyDivision,triangles
	--type: var(--drawType, lines); 
	--size: 120;
	--line-color: #E0AF53;
	--line-width: 2;
}



// Pure CSS Variable Toggling
input[name="drawing"] {
	visibility: hidden;
	display: none;

	&:checked + label {
		background: var(--c-primary);
		color: var(--c-light);
	}
}

input[value="lines"]:checked ~ .card {
		--drawType: lines;
}

input[value="joyDivision"]:checked ~ .card {
		--drawType: joyDivision;
}

input[value="triangles"]:checked ~ .card {
	--drawType: triangles;
}

input[name="size"]{
	justify-self: center;
	align-self: center;
	grid-area: number;
	width: 100px;
}


// CSS Styling
.card {
	justify-self: center;
	align-self: center;
	grid-area: card;
	
	position: relative;
	display: flex;
	margin: 2em;
	width: 100%;
	height: 100vh;
	max-width: 520px;
	max-height: 400px;
	padding: 2em;
	box-shadow: 0 30px 60px 0 rgba(0, 0, 0, 0.2);
	border-radius: 2em;
}

.label {
	justify-self: center;
	align-self: center;
	font-family: "Roboto", sans-serif;
	font-weight: 700;
	letter-spacing: 0.1em;
	color: var(--c-primary);
	border: 2px solid var(--c-primary);
	font-size: 1.4em;
	padding: 0.3em 0.7em;
	border-radius: 0.5em;
	cursor: pointer;
	transition: all 0.3s cubic-bezier(0.39, 0.575, 0.565, 1);
	transition-property: background, color;
}

.form {
	position: relative;
	z-index: 1;
	max-width: 360px;
	margin: auto;
	padding: 45px;
	text-align: center;
}

.form input, .form-input {
	margin: 0 0 15px;
	padding: 15px;
	width: 100%;

	box-sizing: border-box;
	border-radius: .4em;
	font-size: 14px;
	background: rgba(255, 255, 255, 0.8);
	border: 0;
}
.form button {
	padding: 0.5em 0.2em;
	outline: 0;
	width: 100%;
	border: 0;
	border-radius: .4em;

	color: #ffffff;
	font-size: 1em;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	cursor: pointer;

	background: var(--c-primary);
	transition: background-color 0.2s cubic-bezier(0.39, 0.575, 0.565, 1);
}

.form button:hover,
.form button:active,
.form button:focus {
	background: var(--c-secondary);
}

.slider {
  -webkit-appearance: none;
  width: 100%;
  height: 8px;
  border-radius: 5px;  
  background: var(--c-light);
  outline: none;
  opacity: 0.7;
  transition: opacity .2s;
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 25px;
  height: 25px;
  border-radius: 50%; 
  background: var(--c-primary);
  cursor: pointer;
}

.slider::-moz-range-thumb {
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: var(--c-primary);
  cursor: pointer;
}

body {
	background: #2b2b28;
	font-family: "Lora", sans-serif;
	font-size: 16px;
}

* {
	box-sizing: border-box;
}

.wrapper {
	position: relative;
	min-height: 100vh;
	padding: 50px 15px;
	display: grid;
	grid-template-columns: 1fr 1fr 1fr;
	grid-template-rows: 60px 20px 1fr;
	grid-gap: 20px;
	grid-template-areas: 
		"btn-1 btn-2 btn-3"
		". number ."
		"card card card";
	justify-content: space-around;
	align-items: center;
}

.warning:after {
	content: "Sorry your browser doesn't support the CSS Paint API!";
	position: fixed;
	top: 0;
	left: 0;
	text-align: center;
	width: 100%;
	padding: 1em 0;
	background: var(--c-primary);
	color: var(--c-light);
}

.credit {
	display: block;
	position: absolute;
	bottom: 30px;
	right: 30px;
	color: var(--c-light);

	a {
		color: inherit;
	}
}
The Future of CSS: Exploring CSS Custom Properties and Houdini

Javascript Code:

ADVERTISEMENT

CSS Paint API-based “generative” custom paint worklet for CSS Houdini. Three different patterns can be displayed by the worklet: “lines,” “triangles,” and “Joy Division,” each having a variety of adjustable characteristics like size, line color, and line width. These patterns are generated based on the kind and properties selected, and the resulting visuals are then applied as a background picture to HTML components using CSS custom properties.

ADVERTISEMENT

if (typeof registerPaint !== "undefined") {
  registerPaint("generative", class {

    static get inputProperties() {
      return ["--type", "--size", "--line-color", "--line-width"];
    }

    drawLines(ctx, width, height, size) {
      for (let y = 0; y <= height; y += size) {
        for (let x = 0; x <= width; x += size) {
          let leftToRight = Math.random() >= 0.5;

          if (leftToRight) {
            ctx.moveTo(x, y + size);
            ctx.lineTo(x + size, y);
          } else {
            ctx.moveTo(x, y);
            ctx.lineTo(x + size, y + size);
          }

          ctx.stroke();
        }
      }
    }
		
		drawTriangles(ctx, width, height, size) {
			let line, dot,
				odd = false,
				lines = [],
				gap = size;
			
			for (let y = -40; y <= width + 40; y += gap) {
				odd = !odd;
				line = [];
				for (let x = -40; x <= width + 40; x += gap) {
					dot = {
						x: x + (odd ? gap / 2 : 0),
						y: y
					};
					line.push({
						x: x + (Math.random() * .8 - .4) * gap + (odd ? gap / 2 : 0),
						y: y + (Math.random() * .8 - .4) * gap
					});
					ctx.fill();
				}
				lines.push(line);
			}

			function drawTriangle(pointA, pointB, pointC) {
				ctx.beginPath();
				ctx.moveTo(pointA.x, pointA.y);
				ctx.lineTo(pointB.x, pointB.y);
				ctx.lineTo(pointC.x, pointC.y);
				ctx.lineTo(pointA.x, pointA.y);
				ctx.closePath();
				ctx.stroke();
			}
			
			let dotLine;
			odd = true;
			for(let y = 0; y < lines.length - 1; y++) {
				odd = !odd;
				dotLine = [];
				for(let i = 0; i < lines[y].length; i++) {
					dotLine.push(odd ? lines[y][i]   : lines[y+1][i]);
					dotLine.push(odd ? lines[y+1][i] : lines[y][i]);
				}
				for(let i = 0; i < dotLine.length - 2; i++) {
					drawTriangle(dotLine[i], dotLine[i+1], dotLine[i+2]);
				}
			}

		}
		
		drawJoyDivision(ctx, width, height, size) {
			var lines = [];
			let step = size / 2;

			// Create the lines
			for (var i = -40; i <= width + 40; i += step) {
				var line = [];
				for (var j = -40; j <= width + 40; j += step) {
					var distanceToCenter = Math.abs(j - width / 2);
					var variance = Math.max(width / 2 - 50 - distanceToCenter, 0);
					var random = Math.random() * variance / 2 * -1;
					var point = {
						x: j,
						y: i + random
					};
					line.push(point);
				}
				lines.push(line);
			}

			// Do the drawing
			for (var i = 0; i < lines.length; i++) {
				ctx.beginPath();
				ctx.moveTo(lines[i][0].x, lines[i][0].y);

				for (var j = 0; j < lines[i].length - 2; j++) {
					var xc = (lines[i][j].x + lines[i][j + 1].x) / 2;
					var yc = (lines[i][j].y + lines[i][j + 1].y) / 2;
					ctx.quadraticCurveTo(lines[i][j].x, lines[i][j].y, xc, yc);
				}

				ctx.quadraticCurveTo(lines[i][j].x, lines[i][j].y, lines[i][j + 1].x, lines[i][j + 1].y);
				ctx.save();
				ctx.globalCompositeOperation = 'destination-out';
				ctx.fill();
				ctx.restore();
				ctx.stroke();
			}
		}

    paint(ctx, geom, properties) {
      let drawType = String(properties.get("--type")).replace(' ', '');
      let size = Number(properties.get("--size"));
      let lineWidth = Number(properties.get("--line-width"));
      let lineColor = String(properties.get("--line-color"));

      let {
        width,
        height
      } = geom;
      ctx.lineWidth = lineWidth;
      ctx.strokeStyle = lineColor;
			
			const drawFunctions = {
				"lines":  () => this.drawLines(ctx, width, height, size),
				"joyDivision": () => this.drawJoyDivision(ctx, width, height, size),
				"triangles": () => this.drawTriangles(ctx, width, height, size),
			};
			
			drawFunctions[drawType]();
    }
  });
}


ADVERTISEMENT

Conclusion

The future of online styling is bright thanks to CSS Custom Properties and CSS Houdini. They give developers greater creative freedom while encouraging cleaner, easier-to-maintain code.

Being a web developer at this time is exciting as browser support for these technologies continues to expand. Unquestionably, more captivating and visually attractive websites will result from the ability to generate custom CSS attributes and design original rendering and animation effects.

If you find this Blog helpful, then make sure to search Codewithrandom on Google for Front End Projects with Source codes and make sure to Follow the Code with Random Instagram page.



Leave a Reply