Kỹ thuật CSS cho hiệu ứng gợn vật liệu

Hướng dẫn về các kỹ thuật khác nhau cho hiệu ứng gợn bằng CSS và JavaScript

Gần đây tôi đã phải thực hiện hiệu ứng gợn từ thiết kế vật liệu vào một ứng dụng web. Và sau đó tôi nhận ra tôi không biết làm thế nào nó được thực hiện. Điều này dẫn tôi vào một hành trình nghiên cứu các triển khai hiện có, và thậm chí đưa ra một kỹ thuật hoàn toàn mới có thể hữu ích cho bạn.

Hiệu ứng gợn này là gì?

Đợi đã, bạn không biết hiệu ứng gợn từ Thiết kế Vật liệu Google Google? Bạn đã sống trên một hang động trong bao nhiêu năm?

Hiệu ứng gợn được sử dụng khi bạn nhấn nút. Nó hoạt động theo cách tương tự cho các tương tác chuột hoặc chạm.

Vị trí bạn nhấp hoặc chạm vào nút được gọi là điểm liên lạc. Từ đó, một gợn được gửi đi ra ngoài, mất độ mờ khi nó lớn hơn cho đến khi lấp đầy toàn bộ nút. Sau đó nó biến mất hoàn toàn.

Động lực của hiệu ứng gợn này tương tự như gợn sóng bạn nhận được khi bạn chạm vào bề mặt chất lỏng, hoặc khi bạn thả một hòn đá xuống hồ.

Những gợn sóng bạn sẽ tìm thấy trên web

Sau khi thực hiện một số nghiên cứu, tôi có thể tìm thấy hai kỹ thuật chính được sử dụng để thực hiện hiệu ứng gợn trên các ứng dụng web.

Sử dụng :: sau phần tử giả

Sử dụng kỹ thuật này, phần tử giả sau nút được tạo kiểu như một vòng tròn bán trong suốt và hoạt hình để phát triển và mờ dần. Nút chứa cần phải có tràn: ẩn để vòng tròn không bao giờ tràn ra ngoài nút Bề mặt và vị trí: tương đối để giúp dễ dàng định vị vòng tròn trong nút. Bạn có thể đọc thêm chi tiết về kỹ thuật này trên bài viết này của Ionuț Colceriu.

Một trong những điều tuyệt vời về kỹ thuật này là nó là một giải pháp CSS thuần túy cho hiệu ứng gợn. Tuy nhiên, hiệu ứng gợn luôn bắt đầu từ trung tâm của nút, thay vì điểm tiếp xúc. Đó không phải là phản hồi tự nhiên nhất.

Nó có thể được cải thiện bằng cách sử dụng JavaScript để lưu trữ điểm tiếp xúc và sử dụng nó để định vị Ripple. Đó chính xác là những gì mà vật liệu đã làm cho thành phần Ripple web của họ. Nó sử dụng các biến CSS để lưu trữ điểm tiếp xúc và phần tử giả sau khi sử dụng các biến này để định vị.

Sử dụng các yếu tố con

Về bản chất, kỹ thuật này sử dụng chiến lược giống như trước đây. Nhưng thay vì một phần tử giả, nó thêm một phần tử span bên trong nút, sau đó có thể được định vị thông qua JavaScript. Kỹ thuật này được mô tả trên bài viết này của Jhey Tompkins.

Việc thực hiện đơn giản nhất tạo ra một khoảng cho mỗi lần nhấp vào nút và sử dụng vị trí chuột trên sự kiện nhấp để thay đổi vị trí của khoảng đó. Một hình ảnh động CSS làm cho nhịp phát triển và mờ dần cho đến khi trở nên hoàn toàn trong suốt. Chúng ta có thể chọn xóa khoảng cách khỏi DOM sau khi hoạt ảnh kết thúc hoặc chỉ để nó ở dưới thảm - không ai thực sự nhận thấy một khoảng trong suốt treo xung quanh.

Tôi đã tìm thấy một biến thể khác của điều này, trong đó phần tử con là một Svg thay vì một khoảng và Svg được hoạt hình thông qua JavaScript. Biến thể này được giải thích bởi Dennis Gaebel, nhưng về bản chất nó có vẻ giống nhau, và có lẽ cho phép sử dụng các hình dạng và hiệu ứng SVG phức tạp.

Một vấn đề với trình đầu vào

Cả hai kỹ thuật được mô tả ở trên có vẻ tuyệt vời. Nhưng đây là những gì xảy ra khi tôi cố gắng áp dụng chúng trên các phần tử đầu vào với type = submit:

Tại sao don sắt họ làm việc?

Phần tử đầu vào là một phần tử thay thế. Nói tóm lại, điều đó có nghĩa là có rất ít bạn có thể làm với các yếu tố đó, liên quan đến DOM và CSS. Cụ thể, họ có thể có các phần tử con và cũng không có phần tử giả. Bây giờ nó rõ ràng tại sao những kỹ thuật này thất bại.

Vì vậy, nếu bạn sử dụng Thiết kế Vật liệu, tốt hơn hết là tránh xa đầu vào [type = submit] và bám vào các yếu tố nút. Hoặc tiếp tục đọc.

Thêm gợn để gửi đầu vào

Trên ứng dụng web tôi đang làm việc, chúng tôi đã có rất nhiều nút gửi. Thay đổi tất cả chúng để trở thành một yếu tố khác nhau sẽ đòi hỏi rất nhiều công việc và có nguy cơ cao phá vỡ các bảng định kiểu và logic JavaScript. Vì vậy, tôi đã phải tìm ra cách thêm gợn vào các nút gửi hiện có.

Sử dụng hộp đựng

Tôi nhanh chóng nhận ra rằng tôi có thể bọc nút gửi bên trong một phần tử khối nội tuyến và sử dụng phần tử khối nội tuyến làm bề mặt gợn. Đây là một bản demo nhanh:

Mặc dù tôi thích giải pháp này vì sự đơn giản của nó, nó vẫn yêu cầu tôi thay đổi đánh dấu ở quá nhiều nơi. Và tôi biết rằng đó sẽ là một giải pháp mong manh - các nhà phát triển mới sẽ tham gia vào dự án và tạo các nút gửi mà không cần bọc chúng đúng cách trong một bề mặt gợn sóng. Vì vậy, tôi tiếp tục tìm kiếm các giải pháp khác mà không yêu cầu thay đổi DOM.

Độ dốc xuyên tâm

Cú pháp radial-gradient cho phép tôi kiểm soát cả tâm và kích thước của gradient. Tất nhiên, nó cũng cho phép tôi kiểm soát màu của gradient, bao gồm cả các màu bán trong suốt. Và nó không bao giờ vượt quá yếu tố mà nó áp dụng. Vì vậy, có vẻ như nó đã làm mọi thứ tôi cần!

Không nhanh như vậy, có một điều còn thiếu: thuộc tính hình ảnh nền không thể hoạt hình. Tôi không thể làm cho gradient tăng dần và mờ dần trong suốt bằng cách sử dụng hoạt hình CSS. Tôi đã cố gắng làm cho nó phát triển bằng cách tạo hiệu ứng cho thuộc tính kích thước nền, nhưng đó là tất cả những gì tôi có thể làm.

Tôi đã thử một vài thứ khác, chẳng hạn như có một vòng tròn mờ dần như một hình ảnh hoạt hình (sử dụng định dạng apng) và áp dụng nó làm hình nền. Nhưng sau đó tôi không thể kiểm soát khi vòng lặp hình ảnh bắt đầu và kết thúc.

Cuối cùng, một giải pháp với JavaScript

Những gì bạn có thể làm được trong CSS, bạn có thể làm điều đó bằng JavaScript. Sau khi dành nhiều thời gian hơn tôi, tôi sẵn sàng thừa nhận đã cố gắng để hiệu ứng này hoạt động bằng cách sử dụng hoạt hình CSS, tôi đã từ bỏ và quyết định viết hoạt hình bằng JavaScript.

Tôi đã bắt đầu với giải pháp gradient hướng tâm ở trên và sử dụng window.requestAnimationFrame để tạo một hình ảnh động của gradient xuyên tâm, phát triển và mờ dần. Đây là giải pháp cuối cùng của tôi:

Phần kết luận

Vì vậy, có thể có hiệu ứng gợn trên các nút gửi, không chỉ với CSS.

Tôi không thể tìm thấy kỹ thuật này được ghi lại ở bất cứ đâu trên web, vì vậy tôi gọi nó là của riêng tôi. Kỹ thuật Ripple của Leonardo không yêu cầu thay đổi đối với DOM và hoạt động đối với bất kỳ phần tử nào vì nó không dựa vào các phần tử giả hoặc phần tử con. Tuy nhiên, nó không phải là một giải pháp hoàn hảo.

Đầu tiên, có hiệu suất của bạn. Bằng cách tạo hiệu ứng gradient với JavaScript, bạn sẽ mất rất nhiều tối ưu hóa trình duyệt. Nhưng, vì thuộc tính duy nhất được thay đổi là hình nền, tôi sẽ nghi ngờ rằng các trình duyệt sẽ không cần chỉnh lại và sẽ chỉ yêu cầu áp dụng lại các kiểu và sơn lại phần tử. Trong thực tế, đó là chính xác những gì xảy ra, và hiệu suất thực sự tốt. Ngoại lệ cho tuyên bố đó là Firefox Mobile, vì một số lý do không theo kịp hoạt hình. (chỉnh sửa: hoạt ảnh mượt mà trên các phiên bản Firefox Mobile hiện đại)

Thứ hai, kỹ thuật sử dụng thuộc tính hình ảnh nền của nút. Nếu thiết kế của bạn yêu cầu các nút của bạn có hình ảnh được áp dụng cho nền của nó, hiệu ứng gợn sẽ ghi đè lên đó. Nếu bạn thực sự cần hình ảnh đó trên thiết kế của mình, thì JavaScript có thể được sửa đổi để vẽ độ dốc xuyên tâm trên đỉnh của hình nền hiện có.

Thứ ba, điều này dường như không hoạt động trong Internet Explorer. Tuy nhiên, tôi không thấy bất kỳ lý do nào khiến nó không hoạt động với IE10 trở lên. Có thể đó là vì vì IE sử dụng một cú pháp khác nhau cho radial-gradient. Nhưng, ai quan tâm đến IE ngày nay? (chỉnh sửa: phương pháp này hoạt động mà không gặp sự cố nào trên Internet Explorer 11)