Tổng hợp thủ thuật Elementor nâng cao bằng CSS/JS thuần (Không cần cài thêm Plugin)
Mục lục nội dung bài viếtHiện
1. Tại sao nên tự viết CSS/JS thay vì cài Addon Elementor?
Chào bạn! Nếu bạn đã dùng Elementor đủ lâu, chắc hẳn bạn từng gặp tình huống: khách hàng hoặc sếp muốn một hiệu ứng bay lượn bắt mắt, một dải logo chạy ngang không giật lag, hay con trỏ chuột độc đáo. Bản năng đầu tiên của đa số anh em là lên kho WordPress gõ tìm plugin bổ trợ (Addon).
Tuy nhiên, mỗi addon cài thêm thường kéo theo hàng tá thư viện JavaScript cồng kềnh, hàng trăm dòng CSS thừa và làm điểm Google Core Web Vitals (đặc biệt là INP và LCP) sụt giảm thê thảm.
Trong bài viết này, mình sẽ hướng dẫn bạn 5 thủ thuật Elementor nâng cao hoàn toàn bằng CSS và JavaScript thuần. Bạn chỉ cần copy snippet, dán đúng chỗ là chạy ngay, nhẹ tênh và tùy biến 100% theo ý thích!
2. Thủ thuật 1: Hiệu ứng Floating Animation (Bay lơ lửng mềm mại)
Widget mặc định của Elementor chỉ có Motion Effects cơ bản khi cuộn trang, không hỗ trợ chuyển động lơ lửng liên tục (floating) giống các website SaaS hiện đại của Stripe hay Linear.
- Mô tả hiệu ứng: Element (hình ảnh mockup, icon box, hình khối trang trí) sẽ chuyển động nhấp nhô nhẹ nhàng theo trục Y kết hợp xoay góc nhẹ, tạo cảm giác không gian 3D sống động.
- Cách thực hiện:
- Mở trang Elementor, chọn Widget hoặc Container cần tạo hiệu ứng.
- Vào tab Advanced (Nâng cao) > Layout > Thêm class
el-float-itemvào mục CSS Classes. - Dán đoạn mã CSS dưới đây vào Custom CSS của trang hoặc tại Site Settings > Custom CSS.
/* ==========================================================================
Thủ thuật 1: Float Animation cho Elementor Widget
Vị trí: Elementor > Advanced > Custom CSS (hoặc Site Settings)
========================================================================== */
/* Định nghĩa chuyển động bay lơ lửng tối ưu GPU */
@keyframes elPureFloating {
0% {
transform: translateY(0px) rotate(0deg);
}
50% {
transform: translateY(-16px) rotate(1.5deg);
}
100% {
transform: translateY(0px) rotate(0deg);
}
}
/* Áp dụng vào class custom */
.el-float-item {
display: inline-block;
will-change: transform; /* Báo trước trình duyệt tối ưu render GPU */
animation: elPureFloating 4.5s ease-in-out infinite;
}
/* Tùy chọn: Chuyển động lệch pha dành cho element kế bên */
.el-float-item.delay-float {
animation-duration: 6s;
animation-delay: -2s;
}
/* Tự động dừng animation khi người dùng bật chế độ giảm chuyển động */
@media (prefers-reduced-motion: reduce) {
.el-float-item {
animation: none !important;
}
}
Giải thích kỹ thuật:
- Thuộc tính
will-change: transformbáo cho trình duyệt đưa element lên lớp kết hợp (compositor layer) riêng, giúp animation chạy ở 60fps mà không gây giật CPU. - Class phụ
.delay-floatgiúp 2 element đứng cạnh nhau không bị bay cùng một nhịp cứng nhắc.
3. Thủ thuật 2: Infinite Marquee (Dải Logo/Đối tác chạy ngang vô tận)
Trước đây nhiều người dùng thẻ HTML <marquee>, nhưng thẻ này đã bị khai tử khỏi chuẩn web hiện đại và gây giật hình. Widget Carousel mặc định của Elementor thì lại phải kéo chuột hoặc ngắt quãng từng slide.
- Mô tả hiệu ứng: Một hàng logo hoặc dòng chữ chuyển động tịnh tiến đều đặn từ phải qua trái, lặp vô tận không để lộ vết ngắt. Khi rê chuột vào, dải logo tự động dừng lại để người dùng xem rõ.
- Cách thực hiện:
- Tạo 1 Container trong Elementor, đặt class
marquee-wrapper. - Bên trong đặt 1 Container con mang class
marquee-track. - Nhân bản nội dung bên trong
marquee-tracklàm 2 lần (để tạo vòng lặp nối đuôi). - Chèn đoạn CSS sau:
- Tạo 1 Container trong Elementor, đặt class
/* ==========================================================================
Thủ thuật 2: Infinite CSS Marquee mượt mà
========================================================================== */
.marquee-wrapper {
overflow: hidden;
width: 100%;
display: flex;
position: relative;
mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%);
-webkit-mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%);
}
.marquee-track {
display: flex;
flex-shrink: 0;
gap: 2.5rem;
align-items: center;
white-space: nowrap;
animation: scrollMarquee 25s linear infinite;
}
/* Dừng animation khi hover */
.marquee-wrapper:hover .marquee-track {
animation-play-state: paused;
}
@keyframes scrollMarquee {
from {
transform: translateX(0%);
}
to {
transform: translateX(-50%);
}
}
Điểm sáng giá: Thuộc tính mask-image: linear-gradient tạo hiệu ứng mờ dần (fade-out) ở 2 bên mép màn hình cực kỳ sang trọng mà không cần chèn các layer che phủ giả lập.
4. Thủ thuật 3: Nút bấm 3D Glow & Vệt sáng quét qua (Shine Sweep Effect)
Widget Button mặc định của Elementor chỉ đổi màu nền đơn điệu khi hover. Để tăng tỷ lệ Click-through rate (CTR), chúng ta sẽ thêm vệt sáng chóa qua nút (Shine Sweep) kèm vầng hào quang rực rỡ.
- Cách thực hiện: Đặt class
btn-shine-glowcho Widget Button của Elementor.
/* ==========================================================================
Thủ thuật 3: Shine Sweep & Glow Effect cho Button
========================================================================== */
.btn-shine-glow .elementor-button {
position: relative;
overflow: hidden;
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 15px rgba(0, 115, 230, 0.2);
}
/* Vầng sáng phía sau khi hover */
.btn-shine-glow .elementor-button:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(0, 115, 230, 0.45);
}
/* Tạo dải sáng ánh kim quét chéo */
.btn-shine-glow .elementor-button::after {
content: '';
position: absolute;
top: -50%;
left: -60%;
width: 40%;
height: 200%;
background: linear-gradient(
60deg,
rgba(255, 255, 255, 0) 20%,
rgba(255, 255, 255, 0.45) 50%,
rgba(255, 255, 255, 0) 80%
);
transform: rotate(25deg);
transition: none;
pointer-events: none;
}
/* Kích hoạt chuyển động quét khi hover */
.btn-shine-glow .elementor-button:hover::after {
left: 140%;
transition: left 0.75s ease-in-out;
}
5. Thủ thuật 4: Con trỏ chuột tương tác (Custom Smooth Cursor)
- Mô tả hiệu ứng: Thay thế con trỏ mũi tên khô cứng bằng một chấm nhỏ tròn định vị và một vòng tròn lớn đi theo sau với độ trễ mượt mà (lerp smoothing), phóng to khi chạm vào link hoặc nút bấm.
- Cách thực hiện: Tạo một Widget HTML kéo vào Footer của trang, dán toàn bộ khối code sau:
<!-- Cấu trúc DOM cho Custom Cursor -->
<div class="cursor-dot"></div>
<div class="cursor-outline"></div>
<style>
/* Ẩn con trỏ mặc định trên thiết bị có chuột */
@media (hover: hover) and (pointer: fine) {
.cursor-dot, .cursor-outline {
pointer-events: none;
position: fixed;
top: 0;
left: 0;
border-radius: 50%;
z-index: 999999;
transform: translate(-50%, -50%);
transition: opacity 0.3s ease;
}
.cursor-dot {
width: 8px;
height: 8px;
background-color: #6366f1;
}
.cursor-outline {
width: 36px;
height: 36px;
border: 2px solid rgba(99, 102, 241, 0.5);
transition: width 0.2s ease, height 0.2s ease, border-color 0.2s ease;
}
/* Trạng thái khi hover vào thẻ tương tác */
.cursor-hover .cursor-outline {
width: 60px;
height: 60px;
border-color: #ec4899;
background: rgba(236, 72, 153, 0.1);
}
}
@media (hover: none) or (pointer: coarse) {
.cursor-dot, .cursor-outline { display: none !important; }
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Chỉ kích hoạt trên desktop
if (window.matchMedia('(hover: hover) and (pointer: fine)').matches) {
const dot = document.querySelector('.cursor-dot');
const outline = document.querySelector('.cursor-outline');
let mouseX = 0, mouseY = 0;
let outlineX = 0, outlineY = 0;
window.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
dot.style.transform = `translate3d(${mouseX}px, ${mouseY}px, 0) translate(-50%, -50%)`;
});
// Vòng lặp vật lý giúp vòng tròn di chuyển mượt mà (Linear Interpolation)
function animateCursor() {
outlineX += (mouseX - outlineX) * 0.15;
outlineY += (mouseY - outlineY) * 0.15;
outline.style.transform = `translate3d(${outlineX}px, ${outlineY}px, 0) translate(-50%, -50%)`;
requestAnimationFrame(animateCursor);
}
animateCursor();
// Bắt sự kiện hover các thành phần tương tác
const targets = document.querySelectorAll('a, button, .elementor-button, input, textarea');
targets.forEach(el => {
el.addEventListener('mouseenter', () => document.body.classList.add('cursor-hover'));
el.addEventListener('mouseleave', () => document.body.classList.remove('cursor-hover'));
});
}
});
</script>
6. Thủ thuật 5: Bộ đếm số tăng dần khi cuộn tới (Count-Up Animation JS thuần)
Widget Counter của Elementor chỉ đếm số nguyên đơn giản và hay bị lỗi lặp lại khi cuộn. Đoạn code JS dưới đây sử dụng IntersectionObserver chuẩn hiệu năng cao, hỗ trợ đếm số thập phân, phần trăm và tiền tệ.
- Cách thực hiện: Tạo Widget Text Editor hoặc Heading, gán class
custom-countervà thuộc tínhdata-target="1500".
<span class="custom-counter" data-target="99.8" data-decimals="1" data-prefix="" data-suffix="%">0</span>
<script>
(function() {
const counters = document.querySelectorAll('.custom-counter');
if (!counters.length) return;
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
const target = parseFloat(el.getAttribute('data-target')) || 0;
const decimals = parseInt(el.getAttribute('data-decimals')) || 0;
const prefix = el.getAttribute('data-prefix') || '';
const suffix = el.getAttribute('data-suffix') || '';
const duration = 2000; // 2 giây
const startTime = performance.now();
function updateCount(currentTime) {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
// Easing cubic ease-out giúp số chạy chậm dần về đích
const easeOutProgress = 1 - Math.pow(1 - progress, 3);
const currentVal = (easeOutProgress * target).toFixed(decimals);
el.textContent = `${prefix}${currentVal}${suffix}`;
if (progress < 1) {
requestAnimationFrame(updateCount);
} else {
el.textContent = `${prefix}${target.toFixed(decimals)}${suffix}`;
}
}
requestAnimationFrame(updateCount);
obs.unobserve(el); // Chỉ chạy 1 lần khi cuộn tới
}
});
}, { threshold: 0.3 });
counters.forEach(counter => observer.observe(counter));
})();
</script>
7. Lưu ý thực chiến khi chèn Code vào Elementor
- Luôn dán CSS vào Site Settings > Custom CSS thay vì dán rải rác từng widget để dễ quản lý và nén cache.
- Với JavaScript, hãy ưu tiên đưa vào file
custom.jstrong Child Theme hoặc gắn qua hookwp_footerđể tránh blocking render. - Luôn kiểm tra giao diện trên Mobile để tắt các animation không cần thiết, giúp tiết kiệm pin cho người dùng.
🏷️ Lời kết
Hy vọng 5 thủ thuật trên sẽ giúp website Elementor của bạn trở nên chuyên nghiệp, cuốn hút và khác biệt hoàn toàn so với những giao diện kéo thả mặc định. Đừng quên backup giao diện trước khi thêm code nhé!
💬 Bạn ấn tượng nhất với hiệu ứng nào trong 5 cái trên? Hay bạn đang cần viết snippet cho hiệu ứng nào khác? Hãy để lại comment bên dưới, mình sẽ giải đáp và gửi tặng snippet nhé!
