Hiệu ứng di chuột ưa thích cho hình đại diện của bạn

Hiệu ứng di chuột ưa thích cho hình đại diện của bạn

Bạn có biết loại hiệu ứng mà đầu của ai đó thò qua một vòng tròn hoặc lỗ không? Phim hoạt hình Porky Pig nổi tiếng trong đó cậu bé vẫy tay chào tạm biệt trong khi chui ra khỏi một loạt vòng tròn màu đỏ là một ví dụ hoàn hảo, và Kilian Valkhof thực sự đã tạo lại nó ở đây trên CSS-Tricks một thời gian trước.

Tôi có một ý tưởng tương tự nhưng giải quyết theo một cách khác và với một chút hoạt ảnh. Tôi nghĩ nó khá thiết thực và tạo ra hiệu ứng di chuột gọn gàng mà bạn có thể sử dụng trên thứ gì đó như hình đại diện của chính mình.

Thấy không? Chúng ta sẽ tạo một hoạt ảnh mở rộng trong đó hình đại diện dường như bật ra khỏi vòng kết nối. Thật tuyệt, phải không? Đừng nhìn vào mã và hãy cùng nhau xây dựng hoạt hình này từng bước.

HTML: Chỉ một yếu tố

Nếu bạn chưa kiểm tra mã của bản trình diễn và bạn đang tự hỏi có bao nhiêu divĐiều này sẽ mất, sau đó dừng ngay tại đó, bởi vì phần đánh dấu của chúng tôi không có gì khác ngoài một phần tử hình ảnh duy nhất:

<img src="" alt="">

Vâng, một yếu tố duy nhất! Phần thử thách của bài tập này là sử dụng số lượng mã nhỏ nhất có thể. Nếu bạn đã từng theo tôi trong một thời gian, bạn nên quen với điều này. Tôi cố gắng hết sức để tìm các giải pháp CSS có thể đạt được với mã nhỏ nhất, dễ bảo trì nhất có thể.

Tôi đã viết một loạt các bài báo ở đây trên Thủ thuật CSS nơi tôi khám phá các hiệu ứng di chuột khác nhau bằng cách sử dụng cùng một đánh dấu HTML có chứa một phần tử. Tôi đi sâu vào chi tiết về độ dốc, tạo mặt nạ, cắt, phác thảo và thậm chí cả kỹ thuật bố cục. Tôi thực sự khuyên bạn nên kiểm tra chúng vì tôi sẽ sử dụng lại nhiều thủ thuật trong bài đăng này.

Một tệp hình ảnh vuông với nền trong suốt sẽ hoạt động tốt nhất cho những gì chúng ta đang làm. Đây là cái tôi đang sử dụng nếu bạn muốn bắt đầu với nó.

Hiệu ứng di chuột lạ mắt cho hình đại diện của bạn Thông minh dữ liệu PlatoBlockchain. Tìm kiếm dọc. Ái.
Thiết kế bởi cang

Tôi hy vọng sẽ thấy nhiều ví dụ về điều này nhất có thể bằng cách sử dụng hình ảnh thực — vì vậy vui lòng chia sẻ kết quả cuối cùng của bạn trong phần nhận xét khi bạn hoàn thành để chúng tôi có thể xây dựng bộ sưu tập!

Trước khi chuyển sang CSS, trước tiên chúng ta hãy phân tích hiệu ứng này. Hình ảnh trở nên lớn hơn khi di chuột, vì vậy chúng tôi chắc chắn sẽ sử dụng transform: scale() trong đó. Có một vòng tròn phía sau hình đại diện và độ dốc xuyên tâm sẽ thực hiện thủ thuật. Cuối cùng, chúng ta cần một cách để tạo đường viền ở dưới cùng của vòng tròn để tạo ra giao diện của hình đại diện phía sau vòng tròn.

Cùng bắt tay vào làm!

hiệu ứng quy mô

Hãy bắt đầu bằng cách thêm biến đổi:

img { width: 280px; aspect-ratio: 1; cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}

Chưa có gì phức tạp phải không? Tiếp tục nào.

Hình tròn

Chúng tôi đã nói rằng nền sẽ là một gradient xuyên tâm. Điều đó thật hoàn hảo vì chúng ta có thể tạo các điểm dừng cứng giữa các màu của dải màu xuyên tâm, làm cho nó trông giống như chúng ta đang vẽ một vòng tròn bằng các đường nét liền.

img { --b: 5px; /* border width */ width: 280px; aspect-ratio: 1; background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, #0000 ); cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}

Lưu ý biến CSS, --b, tôi đang sử dụng ở đó. Nó đại diện cho độ dày của “đường viền” thực sự chỉ được sử dụng để xác định các điểm dừng màu cứng cho phần màu đỏ của dải màu xuyên tâm.

Bước tiếp theo là chơi với kích thước gradient khi di chuột. Hình tròn cần giữ nguyên kích thước khi hình ảnh phát triển. Vì chúng tôi đang áp dụng một scale() chuyển đổi, chúng ta thực sự cần phải giảm kích thước của vòng tròn vì nếu không thì nó sẽ tăng tỷ lệ với hình đại diện. Vì vậy, trong khi hình ảnh tăng tỷ lệ, chúng ta cần độ dốc để giảm tỷ lệ.

Hãy bắt đầu bằng cách xác định một biến CSS, --f, xác định "hệ số tỷ lệ" và sử dụng hệ số tỷ lệ này để đặt kích thước của vòng tròn. Tôi đang sử dụng 1 làm giá trị mặc định, vì đó là tỷ lệ ban đầu cho hình ảnh và hình tròn mà chúng tôi chuyển đổi từ đó.

Đây là một bản demo để minh họa thủ thuật. Di chuột để xem những gì đang xảy ra đằng sau hậu trường:

Tôi đã thêm một màu thứ ba vào radial-gradient để xác định rõ hơn khu vực của gradient khi di chuột:

radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, lightblue
);

Bây giờ chúng ta phải đặt nền của chúng ta ở tâm của vòng tròn và đảm bảo rằng nó chiếm toàn bộ chiều cao. Tôi muốn khai báo mọi thứ trực tiếp trên background tốc ký, vì vậy chúng tôi có thể thêm định vị nền của mình và đảm bảo rằng nó không lặp lại bằng cách xử lý các giá trị đó ngay sau radial-gradient():

background: radial-gradient() 50% / calc(100% / var(--f)) 100% no-repeat;

Nền được đặt ở trung tâm (50%), có chiều rộng bằng calc(100%/var(--f)), và có chiều cao bằng 100%.

Không có gì quy mô khi --f bằng 1 - một lần nữa, quy mô ban đầu của chúng tôi. Trong khi đó, gradient chiếm toàn bộ chiều rộng của vùng chứa. Khi chúng ta tăng --f, kích thước của phần tử tăng lên — nhờ vào scale() biến đổi - và kích thước của gradient giảm.

Đây là những gì chúng tôi nhận được khi áp dụng tất cả những điều này vào bản demo của mình:

Chúng ta đang đến gần hơn! Chúng tôi có hiệu ứng tràn ở trên cùng, nhưng chúng tôi vẫn cần ẩn phần dưới cùng của hình ảnh, vì vậy có vẻ như nó đang bật ra khỏi vòng tròn chứ không phải nằm phía trước nó. Đó là phần phức tạp của toàn bộ vấn đề này và là điều chúng ta sẽ làm tiếp theo.

đường viền dưới cùng

Lần đầu tiên tôi thử giải quyết vấn đề này với border-bottom thuộc tính, nhưng tôi không thể tìm cách khớp kích thước của đường viền với kích thước của hình tròn. Đây là điều tốt nhất tôi có thể nhận được và bạn có thể thấy ngay nó sai:

Giải pháp thực tế là sử dụng outline tài sản. Đúng, outline, Chứ không phải border. Trong một bài viết trước, tôi chỉ cách outline mạnh mẽ và cho phép chúng tôi tạo các hiệu ứng di chuột thú vị. Kết hợp với outline-offset, chúng tôi có chính xác những gì chúng tôi cần cho hiệu ứng của mình.

Ý tưởng là thiết lập một outline trên hình ảnh và điều chỉnh độ lệch của nó để tạo đường viền dưới cùng. Độ lệch sẽ phụ thuộc vào hệ số tỷ lệ giống như cách mà kích thước độ dốc đã làm.

Bây giờ chúng ta có “đường viền” phía dưới (thực ra là một outline) kết hợp với “đường viền” được tạo bởi gradient để tạo thành một vòng tròn đầy đủ. Chúng ta vẫn cần ẩn các phần của outline (từ trên cùng và các bên), mà chúng ta sẽ xem xét ngay sau đây.

Đây là mã của chúng tôi cho đến nay, bao gồm một vài biến CSS khác mà bạn có thể sử dụng để định cấu hình kích thước hình ảnh (--s) và màu “đường viền” (--c):

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50% / calc(100% / var(--f)) 100% no-repeat; transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}

Vì chúng tôi cần một đường viền dưới hình tròn, chúng tôi đã thêm một border-radius ở phía dưới, cho phép outline để phù hợp với độ cong của gradient.

Tính toán được sử dụng trên outline-offset đơn giản hơn rất nhiều so với vẻ ngoài của nó. Theo mặc định, outline được vẽ bên ngoài của hộp phần tử. Và trong trường hợp của chúng tôi, chúng tôi cần nó để trùng lặp phần tử. Chính xác hơn, chúng ta cần nó đi theo vòng tròn được tạo bởi gradient.

Sơ đồ chuyển nền.
Hiệu ứng di chuột ưa thích cho hình đại diện của bạn

Khi chúng ta chia tỷ lệ phần tử, chúng ta sẽ thấy khoảng cách giữa hình tròn và cạnh. Đừng quên rằng ý tưởng là giữ cho hình tròn có cùng kích thước sau khi chạy phép biến đổi tỷ lệ, điều này để lại cho chúng ta khoảng trống mà chúng ta sẽ sử dụng để xác định phần bù của đường viền như được minh họa trong hình trên.

Đừng quên rằng phần tử thứ hai được chia tỷ lệ, vì vậy kết quả của chúng ta cũng được chia tỷ lệ… có nghĩa là chúng ta cần chia kết quả cho f để có được giá trị bù thực:

Offset = ((f - 1) * S/2) / f = (1 - 1/f) * S/2

Chúng ta thêm dấu âm vì chúng ta cần đường viền đi từ ngoài vào trong:

Offset = (1/f - 1) * S/2

Đây là bản trình diễn nhanh cho thấy cách đường viền tuân theo dải màu:

Bạn có thể đã nhìn thấy nó, nhưng chúng ta vẫn cần đường viền dưới cùng để chồng lên vòng tròn thay vì để nó tràn qua nó. Chúng tôi có thể làm điều đó bằng cách loại bỏ kích thước của đường viền khỏi phần bù:

outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2) - var(--b));

Bây giờ chúng ta cần tìm cách xóa phần trên cùng khỏi đường viền. Nói cách khác, chúng tôi chỉ muốn phần dưới cùng của hình ảnh outline.

Đầu tiên, hãy thêm khoảng trống ở trên cùng với phần đệm để giúp tránh chồng chéo ở trên cùng:

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; padding-block-start: calc(var(--s)/5); /* etc. */
}
img:hover { --f: 1.35; /* hover scale */
}

Không có logic cụ thể nào đối với phần đệm trên cùng đó. Ý tưởng là đảm bảo đường viền không chạm vào đầu của hình đại diện. Tôi đã sử dụng kích thước của phần tử để xác định không gian đó luôn có cùng tỷ lệ.

Lưu ý rằng tôi đã thêm content-box giá trị đối với background:

background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50%/calc(100%/var(--f)) 100% no-repeat content-box;

Chúng tôi cần điều này bởi vì chúng tôi đã thêm phần đệm và chúng tôi chỉ muốn nền được đặt thành hộp nội dung, vì vậy chúng tôi phải thông báo rõ ràng cho nền dừng ở đó.

Thêm mặt nạ CSS vào hỗn hợp

Chúng tôi đã đến phần cuối cùng! Tất cả những gì chúng ta cần làm là giấu một số mảnh, và chúng ta đã hoàn thành. Đối với điều này, chúng tôi sẽ dựa vào mask tài sản và, tất nhiên, độ dốc.

Đây là hình để minh họa cái cần ẩn cái gì cần hiện cái gì cho chính xác hơn

Hiển thị cách mặt nạ áp dụng cho phần dưới cùng của vòng tròn.
Hiệu ứng di chuột ưa thích cho hình đại diện của bạn

Hình ảnh bên trái là những gì chúng tôi hiện có và bên phải là những gì chúng tôi muốn. Phần màu xanh lá cây minh họa mặt nạ chúng ta phải áp dụng cho hình ảnh ban đầu để có được kết quả cuối cùng.

Chúng ta có thể xác định hai phần của mặt nạ:

  • Một phần hình tròn ở phía dưới có cùng kích thước và độ cong như chuyển màu xuyên tâm mà chúng tôi đã sử dụng để tạo hình tròn phía sau hình đại diện
  • Một hình chữ nhật ở trên cùng bao phủ khu vực bên trong đường viền. Lưu ý cách đường viền nằm ngoài vùng màu xanh lục ở trên cùng — đó là phần quan trọng nhất, vì nó cho phép cắt đường viền để chỉ phần dưới cùng hiển thị.

Đây là CSS cuối cùng của chúng tôi:

img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ --_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; --_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); width: var(--s); aspect-ratio: 1; padding-top: calc(var(--s)/5); cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: var(--_o); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000) var(--_g); mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g); transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}

Hãy phá vỡ điều đó mask tài sản. Để bắt đầu, lưu ý rằng một tương tự radial-gradient() từ background tài sản ở trong đó. Tôi đã tạo một biến mới, --_g, cho các phần chung để làm cho mọi thứ bớt lộn xộn.

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);

Tiếp theo, có một linear-gradient() trong đó cũng vậy:

--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);

Điều này tạo ra phần hình chữ nhật của mặt nạ. Chiều rộng của nó bằng chiều rộng của gradient xuyên tâm trừ đi hai lần độ dày của đường viền:

calc(100% / var(--f) - 2 * var(--b))

Chiều cao của hình chữ nhật bằng một nửa, 50%, kích thước của phần tử.

Chúng ta cũng cần gradient tuyến tính được đặt ở trung tâm nằm ngang (50%) và offset từ trên cùng bằng giá trị tương tự như offset của đường viền. Tôi đã tạo một biến CSS khác, --_o, đối với phần bù mà chúng tôi đã xác định trước đó:

--_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));

Một trong những điều khó hiểu ở đây là chúng ta cần một tiêu cực offset cho đường viền (để di chuyển nó từ ngoài vào trong) nhưng tích cực offset cho gradient (để di chuyển từ trên xuống dưới). Vì vậy, nếu bạn thắc mắc tại sao chúng ta nhân phần bù, --_o, Bởi -1, Bây giờ bạn đã biết!

Đây là bản demo để minh họa cấu hình độ dốc của mặt nạ:

Di chuột ở trên và xem mọi thứ di chuyển cùng nhau như thế nào. Hộp ở giữa minh họa lớp mặt nạ bao gồm hai độ dốc. Hãy tưởng tượng nó là phần hiển thị của hình ảnh bên trái và bạn sẽ có kết quả cuối cùng ở bên phải!

Kết thúc

Ồ, chúng ta xong rồi! Và chúng tôi không chỉ kết thúc bằng một hoạt ảnh di chuột mượt mà, mà chúng tôi đã làm tất cả với một HTML duy nhất <img> yếu tố. Chỉ vậy thôi và chưa đến 20 dòng thủ thuật CSS!

Chắc chắn, chúng tôi đã dựa vào một số thủ thuật nhỏ và công thức toán học để đạt được hiệu ứng phức tạp như vậy. Nhưng chúng tôi biết chính xác phải làm gì vì chúng tôi đã xác định trước những phần chúng tôi cần.

Chúng tôi có thể đơn giản hóa CSS nếu chúng tôi cho phép mình có nhiều HTML hơn không? Tuyệt đối. Nhưng chúng ta ở đây để tìm hiểu các thủ thuật CSS mới! Đây là một bài tập tốt để khám phá độ dốc CSS, mặt nạ, outline hành vi của tài sản, biến đổi và nhiều hơn nữa. Nếu bạn cảm thấy lạc lõng tại bất kỳ thời điểm nào, thì hãy chắc chắn kiểm tra loạt bài của tôi sử dụng các khái niệm chung giống nhau. Đôi khi, việc xem thêm các ví dụ và trường hợp sử dụng để hiểu rõ vấn đề hơn đôi khi sẽ hữu ích.

Tôi sẽ để lại cho bạn một bản demo cuối cùng sử dụng ảnh của các nhà phát triển CSS nổi tiếng. Đừng quên cho tôi xem bản demo với hình ảnh của chính bạn để tôi bổ sung vào bộ sưu tập nhé!

Dấu thời gian:

Thêm từ Thủ thuật CSS