Active License Elementor Pro chỉ với 300k/năm/domain Shop Now
Mới Dịch vụ thiết kế website, xử lý mã độc & tối ưu tốc độ chuyên sâu

Code thêm hiệu ứng hạt nền cho section trong Elementor

Section hero nền xanh navy đậm, hàng chục chấm sáng trắng trôi lững lờ và nối nhau bằng sợi mảnh, giữa section là tiêu đề lớn BUILD & SCALE WITH CONFIDENCE và nút Get Started

Bài viết này mình sẽ hướng dẫn bạn cách thêm hiệu ứng hạt nền cho section trong Elementor nhé.

Section hero chỉ có một màu nền phẳng nhìn khá tĩnh, trong khi những chấm sáng nhỏ trôi lững lờ và nối nhau bằng sợi mảnh làm cả section sống động hẳn lên, khách sẽ dừng lại nhìn lâu hơn. Elementor mặc định chỉ có màu nền, ảnh nền, video nền và vài hiệu ứng chuyển động cơ bản, hoàn toàn không có hiệu ứng hạt nền — muốn có thì hoặc cài thêm plugin addon, hoặc tự code. Bài này mình code bằng JavaScript thuần, không cần cài thêm plugin nào nhé.

Thêm code hiệu ứng hạt nền

Bạn chỉ cần thêm code dưới vào cuối file functions.php của child theme nhé. Nhớ sao lưu file trước khi sửa, và đừng chèn vào theme cha vì khi theme cập nhật sẽ mất code.

<?php
// Hieu ung hat nen cho section Elementor - them vao functions.php cua child theme
add_action( 'wp_footer', 'nn_hat_nen_elementor' );
function nn_hat_nen_elementor() {
	if ( ! did_action( 'elementor/loaded' ) ) {
		return;
	}
	?>
	<style>
	.nn-hat-nen { position: relative; overflow: hidden; }
	.nn-hat-nen > canvas.nn-canvas-hat { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
	.nn-hat-nen > .elementor-container { position: relative; z-index: 1; }
	</style>
	<script>
	(function () {
		var sections = document.querySelectorAll('.nn-hat-nen');
		if (!sections.length || window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
			return;
		}
		var KHOANG_CACH_NOI = 110;
		var MAU_HAT = 'rgba(255, 255, 255, 0.85)';
		var MAU_NOI = 'rgba(255, 255, 255, 0.25)';
		sections.forEach(function (section) {
			var canvas = document.createElement('canvas');
			canvas.className = 'nn-canvas-hat';
			section.insertBefore(canvas, section.firstChild);
			var ctx = canvas.getContext('2d');
			var hat = [];
			var rong = 0, cao = 0, dang_hien = true;
			var chuot = { x: -9999, y: -9999 };
			function kich_thuoc() {
				rong = section.clientWidth;
				cao = section.clientHeight;
				canvas.width = rong;
				canvas.height = cao;
			}
			kich_thuoc();
			var so_hat = Math.min(90, Math.max(25, Math.floor(rong * cao / 22000)));
			for (var i = 0; i < so_hat; i++) {
				hat.push({
					x: Math.random() * rong,
					y: Math.random() * cao,
					vx: (Math.random() - 0.5) * 0.4,
					vy: (Math.random() - 0.5) * 0.4,
					r: Math.random() * 1.8 + 1
				});
			}
			section.addEventListener('mousemove', function (e) {
				var rect = section.getBoundingClientRect();
				chuot.x = e.clientX - rect.left;
				chuot.y = e.clientY - rect.top;
			});
			section.addEventListener('mouseleave', function () {
				chuot.x = -9999;
				chuot.y = -9999;
			});
			if ('IntersectionObserver' in window) {
				new IntersectionObserver(function (entries) {
					dang_hien = entries[0].isIntersecting;
				}).observe(section);
			}
			window.addEventListener('resize', kich_thuoc);
			function ve() {
				requestAnimationFrame(ve);
				if (!dang_hien) {
					return;
				}
				ctx.clearRect(0, 0, rong, cao);
				for (var i = 0; i < hat.length; i++) {
					var h = hat[i];
					var dx = h.x - chuot.x;
					var dy = h.y - chuot.y;
					var kc_chuot = Math.sqrt(dx * dx + dy * dy);
					if (kc_chuot < 120 && kc_chuot > 0) {
						h.x += dx / kc_chuot * 0.6;
						h.y += dy / kc_chuot * 0.6;
					}
					h.x += h.vx;
					h.y += h.vy;
					if (h.x < 0) { h.x = rong; }
					if (h.x > rong) { h.x = 0; }
					if (h.y < 0) { h.y = cao; }
					if (h.y > cao) { h.y = 0; }
					ctx.beginPath();
					ctx.arc(h.x, h.y, h.r, 0, Math.PI * 2);
					ctx.fillStyle = MAU_HAT;
					ctx.fill();
				}
				for (var a = 0; a < hat.length; a++) {
					for (var b = a + 1; b < hat.length; b++) {
						var ddx = hat[a].x - hat[b].x;
						var ddy = hat[a].y - hat[b].y;
						var kc = Math.sqrt(ddx * ddx + ddy * ddy);
						if (kc < KHOANG_CACH_NOI) {
							ctx.beginPath();
							ctx.moveTo(hat[a].x, hat[a].y);
							ctx.lineTo(hat[b].x, hat[b].y);
							ctx.strokeStyle = MAU_NOI;
							ctx.lineWidth = 1;
							ctx.stroke();
						}
					}
				}
			}
			ve();
		});
	})();
	</script>
	<?php
}

Code trên móc vào wp_footer để in CSS và JavaScript ở cuối trang, chỉ chạy khi Elementor đang hoạt động nhờ kiểm tra did_action(‘elementor/loaded’). JavaScript tìm mọi section có class nn-hat-nen, chèn một thẻ canvas vào đầu mỗi section rồi vẽ các hạt tròn trôi chậm, hạt nào ở gần nhau dưới 110px thì nối bằng một sợi mảnh. Khi bạn di chuột qua section, các hạt gần con trỏ sẽ bị đẩy nhẹ ra xa. Số hạt tự tính theo diện tích section, tối thiểu 25 và tối đa 90 hạt. CSS đặt canvas nằm sau nội dung nhờ z-index và chặn canvas bắt sự kiện chuột bằng pointer-events: none, nên nút bấm và link trong section vẫn bấm bình thường.

Gắn class cho section và kiểm tra hiệu ứng

Bạn mở trang bằng Elementor, bấm vào section muốn thêm hiệu ứng, ở cột bên trái chọn tab Nâng cao, mục Lớp CSS nhập nn-hat-nen rồi bấm Cập nhật. Mở trang ngoài xem thử: các chấm sáng trôi nhẹ trên nền section, di chuột qua thì hạt dạt ra. Hiệu ứng hợp nhất với section có nền tối vì màu hạt trong code đang là trắng; muốn đổi màu hạt thì sửa 2 hằng MAU_HAT và MAU_NOI trong code, ví dụ đổi sang tông xanh dương nhạt rgba(147, 197, 253, 0.85) cho nền sáng.

Section hero nền xanh navy đậm, hàng chục chấm sáng trắng trôi lững lờ và nối nhau bằng sợi mảnh, giữa section là tiêu đề lớn BUILD & SCALE WITH CONFIDENCE và nút Get Started
Kết quả: các hạt sáng trắng trôi và nối nhau bằng sợi mảnh trên nền tối của section hero, di chuột qua hạt sẽ dạt ra.

Lưu ý khi dùng

Code tự dừng vẽ khi section ra khỏi màn hình nhờ IntersectionObserver và tôn trọng tùy chọn giảm chuyển động của trình duyệt qua prefers-reduced-motion, nên không tốn tài nguyên khi khách cuộn qua section khác. Đừng gắn class này cho quá nhiều section trên cùng một trang, mỗi section là một canvas chạy riêng, gắn 2–3 section là vừa. Hiệu ứng này đi chung với bài code thêm hiệu ứng parallax cho ảnh nền section trong Elementor là thành bộ hiệu ứng nền cho section hero.

Kết luận

Vậy là chỉ với 1 đoạn code ngắn bạn đã thêm hiệu ứng hạt nền cho section trong Elementor mà không cần cài thêm plugin rồi nhé. Tính năng này đi chung với bài code thêm hiệu ứng parallax cho ảnh nền section trong Elementor và bài code thêm hiệu ứng gõ chữ cho tiêu đề trong Elementor là thành bộ hiệu ứng động cho trang dựng bằng Elementor.

Nếu cần mình kèm 1-1 về Elementor thì cứ liên hệ mình nhé.

Nhân Viên

Nhân Viên

Web Developer & WordPress Expert

Ngọc Nguyễn - Chuyên gia thiết kế Website WordPress, tối ưu tốc độ 90+ và xử lý dứt điểm mã độc. Đam mê chia sẻ kiến thức hữu ích đến cộng đồng lập trình & webmaster.

Để lại bình luận hoặc thắc mắc

Email của bạn sẽ không được hiển thị công khai.

Ngọc Nguyễn
Ngọc Nguyễn
| Thiết kế Website | Hosting tốc độ cao | Giải pháp hạ tầng | Fix lỗi WordPress, mã độc | Tối ưu tốc độ | Thiết kế Website | Hosting tốc độ cao | Giải pháp hạ tầng | Fix lỗi WordPress, mã độc | Tối ưu tốc độ
Tư vấn miễn phí