動きをランダムにつけて雪を降らせています。

DEMO

わかりやすいように、別ページにDEMOを用意しました。

HTML

JavaScriptで要素を生成しているので、<body>以外は特に表記は必要ありません。

<body></body>

CSS

body {
	background-color: #444;
	margin: 0;
	overflow: hidden;
	padding: 0;
}
.snow {
	background-color: #fff;
	border-radius: 50%;
	height: 20px;
	opacity: .6;
	position: absolute;
	width: 20px;
}

JavaScript

落下速度や揺れ速度は数値を変更して調整してください。

const snowAmount = 100; // 雪の量を設定

let snows = [];

function createSnows() {
	for (let i = 0; i < snowAmount; i++) {
		let snow = document.createElement('div');
		snow.classList.add('snow');

		// 各雪のランダムな初期位置とサイズを設定
		const leftPosition = Math.random() * window.innerWidth;
		const topPosition = Math.random() * window.innerHeight;
		const size = Math.random() * 10 + 5;
		snow.style.left = `${leftPosition}px`;
		snow.style.top = `${topPosition}px`;
		snow.style.width = `${size}px`;
		snow.style.height = `${size}px`;

		// 初期の左右の揺れ方向をランダムに設定
		snow.swayDirection = Math.random() < 0.5 ? 1 : -1; // 左右の揺れ方向
		snow.swayAmount = Math.random() * 10 + 5; // 揺れ幅

		// 雪を画面に追加
		document.body.appendChild(snow);

		// 雪の情報を配列に格納
		snows.push({
			element: snow,
			topPosition: topPosition,
			swayDirection: snow.swayDirection,
			swayAmount: snow.swayAmount,
			speed: Math.random() * 1 + 0.5, // 落下速度
			swaySpeed: Math.random() * 0.02 + 0.01 // 揺れ速度
		});
	}
}

// 雪の位置を更新する関数
function updateSnows() {
	snows.forEach(snow => {
		// 雪の落下位置を更新
		snow.topPosition += snow.speed;
		// 左右の揺れを加える
		const swayOffset = Math.sin(snow.topPosition * snow.swaySpeed) * snow.swayAmount;
		snow.element.style.transform = `translateX(${swayOffset * snow.swayDirection}px)`;

		// 落下位置が画面外に出たら位置をリセット
		if (snow.topPosition > window.innerHeight) {
			snow.topPosition = -20; // 画面外上部から再度降ってくる
			snow.element.style.top = `${snow.topPosition}px`;
		}

		// 雪の位置を更新
		snow.element.style.top = `${snow.topPosition}px`;
	});
}

// ページが読み込まれたときに雪を降らせる
window.onload = function () {
	createSnows();
	setInterval(updateSnows, 16); // 16msごとに更新
};