Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <!-- 
 * HERO SPACE COMPONENT with SHADERZZZ <3
 * Made for FrontendHorse Twitch Stream
 * https://frontend.horse/episode/gorgeous-space-shaders
 *
 * SEPTEMBER 2021
 *
 * By ilithya
 * https://www.ilithya.rocks/
 * https://twitter.com/ilithya_rocks 
-->

<div id="shader" class="c-hero">
<!-- 	<h1>Spacebnb</h1> -->
</div>
<script id="vertex" type="x-shader/x-vertex">
	varying vec2 vUv;

    void main() {
		vUv = (uv - 0.5) * 2.0;
		gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
</script>

<script id="vertex-font" type="x-shader/x-vertex">
	varying vec2 vUv;
	
	uniform vec2 u_ratio;
	
    void main() {
		vUv = uv;
		gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
		vUv = (gl_Position.xy / gl_Position.w);
		vUv *= u_ratio; // Normalized Device Coordinates
    }
</script>

<script id="fragment" type="x-shader/x-fragment">
precision highp float;

varying vec2 vUv;

#define TAU 6.2831853071795864769252867665590

uniform float u_time;
uniform bool u_text;

// https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
float rand(vec2 n) { 
	return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}

float circleShape(in vec2 uv, in float radius) {
    float circle = distance(
        uv, 
        vec2( 
			clamp(
				// tan(u_time * // TRY another effect
				sin(u_time * 0.5 *
					rand(vec2(radius)) 
				),
				0.25,
				0.75
			) 
        ) 
    );

    return smoothstep(
        radius * 0.2,
        radius * 0.21, 
        circle
    );
}
	
void main(void){
	vec2 uv = vUv;

	if (u_text) {
		uv.x -= 2.0; 
		uv.y += 0.5; // TRY 1.0
	}

    float time = u_time;    
    
    // SPACE BACKGROUND
    vec3 color = vec3(0.0);

    float space = atan(uv.x, uv.y) + uv.x;
    space /= TAU; 
    space = fract(space * 3. * 7. + time * 0.1);

    color = vec3(space);
	
	// COLORS
    vec3 c1 = vec3(0.27, 0.32, 0.78); // blue-purple 
    vec3 c2 = vec3(1.1, 1.1, 0.3); // final yellow // Try g - 1.3
    // vec3 c2 = vec3(1.0, 0.87, 0.3); // before yellow
    vec3 c3 = vec3(1.0); // white
    vec3 c4 = vec3(0.57, 0.5, 0.9); // light purple
    vec3 c5 = vec3(0.1, 0.3, 0.4); // aqua
	vec3 c6 = vec3(0.35, 0.0, 1.0); // blue
	vec3 c7 = vec3(0.95); // grayish

	color = mix(c1, c5, color);
    // color = mix(c1, c4, color); // TRY another combination

    // GLOW
    float circle = distance(
        vec2(uv.x, uv.y * 1.5) * 0.5, 
        vec2(-0.2, -0.2)
    );
    vec3 glow = vec3(circle);
    // glow = step(0.3, glow); // TO DEBUG

    glow = smoothstep(0.0, 0.5, glow);
    color = 0.2 + mix(color, glow, color);
    
    // MAIN STAR
    float star = length(uv);
    star = smoothstep(0.0, 0.45, star);

    color *= mix(c2, c3, star);

    // STARDUST
    float i = 45.0;
    vec2 particles = ceil(uv*i);

    float dust = circleShape(
        fract(uv * i),
        rand(particles) 
    );
    
	vec3 gradientBg = mix(c3, c6, length(uv*1.5)); // TRY 1.7
    vec3 gradientDust = mix(c7, c3, length(uv)); // TRY c7 instead
    color *= mix(gradientDust, gradientBg, dust);
	
	if (u_text) {
	 	color += 1.0;
	}
	
    // PAINT SHADER
    gl_FragColor = vec4(color, 1.0);
}
</script>
              
            
!

CSS

              
                $c1: #000; // black
$c2: #EAEAEA; // light gray
$c3: #fdfd05; // yellow 
$c4: #0057f5; // blue

* {
	box-sizing: border-box;
	user-select: none;
}

body {
	height: 100vh;
	background-color: $c1;
	margin: 0;
	padding: 0;
	overflow: hidden;
	position: relative;
	
	display: flex;
	align-items: center;
}

.c-hero {
	width: 100%;
	// height: 100%;
	height: 500px;
	// border: 15px solid #eaeaea; // To debug
	
	display: flex;
	align-items: center;
	justify-content: center;
}

h1 {
	color: rgba(white, 0.95);
	font-family: 'Exo 2', sans-serif;
	font-size: 9vmin;
	font-weight: 700;
	letter-spacing: 3vmin;
	text-transform: uppercase;
	text-shadow: $c3 1px 0 30px;
	position: absolute;
	
	// TRY if uncomment h1 in HTML instead 3D Typo
	// animation: float 3.0s linear alternate infinite;
}

// @keyframes float {
// 	0% {
// 		transform: scale(0.985);
// 	}
// 	100% {
// 		transform: scale(1);
// 	}
// }
              
            
!

JS

              
                /* 
 * HERO SPACE COMPONENT with SHADERZZZ <3
 * Made for FrontendHorse Twitch Stream
 * https://frontend.horse/episode/gorgeous-space-shaders
 *
 * SEPTEMBER 2021
 *
 * By ilithya
 * https://www.ilithya.rocks/
 * https://twitter.com/ilithya_rocks
 */

const container = document.querySelector("#shader");
const scene = new THREE.Scene();
const sizes = {
	w: container.clientWidth, 
	h: container.clientHeight
};
const camera = new THREE.PerspectiveCamera(
	45,
	sizes.w / sizes.h,
	0.1,
	1000
);
camera.position.z = 50;
scene.add(camera);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(sizes.w, sizes.h);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

container.appendChild(renderer.domElement);

// Fn by Daniel Velazquez @Anemolito - It gives you the FOV size from the camera according to screen size looking it as a pyramid
function getViewsizeAtDepth(depth = 0) {
	const fovInRadians = (camera.fov * Math.PI) / 180;
	const height = Math.abs(
	(camera.position.z - depth) * Math.tan(fovInRadians / 2) * 2
	);
	return { width: height * camera.aspect, height };
}
let viewSize = getViewsizeAtDepth();

// SHADER PLANE
const plane = new THREE.PlaneGeometry(1, 1);
const uniforms = {
	u_time: { type: "f", value: 1.0 },
};
const vertexShader = document.getElementById("vertex").textContent;
const fragmentShader = document.getElementById("fragment").textContent;
const planeMaterial = new THREE.ShaderMaterial({
	uniforms,
	vertexShader,
	fragmentShader
});
const planeMesh = new THREE.Mesh(plane, planeMaterial);
scene.add(planeMesh);

// TYPOGRAPHY
const group = new THREE.Group();
const fontLoader = new THREE.FontLoader();
const vertexShaderFont = document.getElementById("vertex-font").textContent;
let u_ratio = new THREE.Uniform(new THREE.Vector2(1.0, 1.0)); 
fontLoader.load(			"https://threejs.org/examples/fonts/droid/droid_sans_bold.typeface.json",
	function (font) {
		const text = `spacebnb`;
		const typoSize = Math.max(
			sizes.w < 800 ? 3.0 : 5.0, 
			Math.round(sizes.w  * .0040)
		);
		const typoProperties = {
			font: font,
			size: typoSize,
			height: 0,	
			curveSegments: 10,
		};
		const textGeometry = new THREE.TextGeometry(text, typoProperties);
		const textMaterial = new THREE.ShaderMaterial({
			vertexShader: vertexShaderFont,
			fragmentShader,
			uniforms: {
				u_ratio,
				u_text: new THREE.Uniform(true),
				u_time: uniforms.u_time,
			},
		});
		// TRY a wireframe material instead
		// const textMaterial = new THREE.MeshBasicMaterial({
		// 	color: '#eaeaea',
		// 	wireframe: true,
		// });
		textGeometry.center();	
		const textMesh = new THREE.Mesh(textGeometry, textMaterial);
		group.position.z = 20;
		group.add(textMesh);
	}
);
scene.add(group);

function onWindowResize() {
	sizes.w = container.clientWidth;
	sizes.h = container.clientHeight;
	
	camera.aspect = sizes.w / sizes.h;
	camera.updateProjectionMatrix();

	renderer.setSize(sizes.w, sizes.h);
		
	viewSize = getViewsizeAtDepth();
	const square = Math.max(viewSize.width, viewSize.height);
	planeMesh.scale.x = square;
	planeMesh.scale.y = square;
	
	u_ratio.value.set(
		Math.min(1, sizes.w / sizes.h), 
		Math.min(1, sizes.h / sizes.w)
	);
}
onWindowResize();
window.addEventListener("resize", onWindowResize);

const clock = new THREE.Clock();
const tick = () => {
	const elapsedTime = clock.getElapsedTime();
	uniforms.u_time.value = elapsedTime;

	const rot = Math.sin(elapsedTime) * 0.075;
	group.rotation.x = rot;
	group.rotation.y = rot;
	
	renderer.render(scene, camera);
	
	requestAnimationFrame(tick);
};
tick();
              
            
!
999px

Console