Tạo Switch UI sử dụng css Mask

1.png

Trong xử lý ảnh. Masking là kỹ thuật cho phép bạn giấu 1 tấm ảnh với 1 tấm khác. Mask được dùng để tạo một phần trong tấm ảnh có thể nhìn xuyên qua. Bạn có thể thực hiện che ảnh bằng Css cùng với sự hỗ trợ của các thuộc tính masking.

Trong bài hôm nay, chúng ta sẽ tạo mộ tấm ảnh được che giấu bằng cách sử dụng 2 ảnh PNG và kỹ thuật CSS masking, và cho phép người dùng chọn 2 trạng thái của tấm ảnh (ngày và đêm) với sự hỗ trợ của switch UI.

2.gif

Bởi vì một số vấn đề trình duyệt tương thích - không phải tất cả các thuộc tính mặt nạ được hỗ trợ ở mọi trình duyệt – tôi sẽ thể hiện 2 kĩ thuật thêm vào, một cho Webkit-based và một cho Firefox. 2 bước đầu tiên trong bài hướng dẫn 3 bước là giống nhau đối với mỗi trình duyệt, nhưng bước thứ ba sẽ khác nhau.

Bước 1. Tạo 1 switch cơ bản

Kể từ khi một switch điển hình có 2 trạng thái với một trạng thái được bật tại một thời điểm, bạn có thể sử dụng một nhóm radio button để tạo ra thành phần hoạt động của switch. Đặt mỗi radio button tại 2 đầu trái và phải của phần tử cha của chúng.

Đặt tên thuộc tính giống nhau cho nhóm radio button. Trong nhóm radio button, chỉ có một nút có thể được kiểm tra tại 1 thời điểm.

Chúng ta bắt đầu với HTML và CSS

<div id="outerWrapper">
    <div id="innerWrapper">
        <input type="radio" id="leftRadio" class="radio" name="radio" />
        <input type="radio" id="rightRadio" class="radio" name="radio" checked />
    </div>
</div>

Trong Css bên dưới, tôi sử dụng “postion: absolute” để đặt radio buttons tại bất cứ nơi nào tôi muốn trên màn hình.

#outerWrapper{
    width: 450px;
    height: 90px;
    padding: 10px;
    margin: 100px auto 0 auto;
    border-radius: 55px;
    box-shadow: 0 0  10px 6px #EAEBED;
    background: #fff;
}
#innerWrapper{
    height:100%;
    border-radius:45px;
    overflow:hidden;
    position:relative;
}
.radio{
    width:90px;
    height:100%;
    position:absolute;
    margin:0;
    opacity: 0;
}
#rightRadio{
    right: 0;
}
.radio:not(:checked){
    cursor: pointer;
}

Tôi thêm “opacity: 0” trong class .radio để giấu radio button đi. Còn câu lệnh “cursor:pointer” để khi di chuột vào radio button khi chưa bật sẽ hiện ra con trỏ chuột, và để người dùng biết đó là nút để nhấn thay đổi trạng thái.

3.jpg

Bước 2. Thêm lớp bao ngoài cho Switch

Trong bước này, chúng ta sẽ thêm 2

cho 2 lớp bao ngoài dưới radio button trong file HTML của chúng ta, và một ảnh nền cho mỗi lớp bao ngoài .

Tôi đang dùng “Ngày” và “Đêm” như 2 trạng thái của switch, lấy ý tưởng từ Dribbble shot của Minh Killy Le.

4.jpg

<div id="daySkin" class="skin"></div>
<div id="nightSkin" class="skin"></div>
#daySkin{
    background-image:url('day.png');
}
#nightSkin{
    background-image:url('night.png');
}
.skin{
    width: 100%;
    height: 100%;
    pointer-events: none;
    position: absolute;
    margin: 0;
}

“pointer-events:none” được sử dụng để khi click sự kiện trên switch sẽ bỏ qua thành phần bên ngoài và tìm đến từng radio button

Với thuộc tính pointer-events bạn có thể thiết lập trong các tình huống mà các thành phần đồ họa có thể là đối tượng được tương tác bởi chuột

Có thể thay thế code phía trên bằng 2 thẻ <img> (với mã nguồn ảnh) trong thẻ <div> . Chúng sẽ là lớp vỏ ngoài cho 2 trạng thái của Switch

5.jpg

Bước 3a. Thêm Mask (Dùng cho Webkit)

Dành cho Chrome và các trình duyêt Webkit-based khác, tôi sẽ dùng thuộc tính CSS: mask-img, chỉ có thể hoạt động khi thêm –webkit trong các trình duyệt Webkit. Mask-img cho phép bạn chỉ định các hình ảnh được sử dụng như mặt nạ.

Có 2 loại mask: Luminance và alpha

  • Khi sử dụng che giấu kiểu Luminance, phần tối của mask-image sẽ che bức ảnh chính: nếu phần tối càng nhiều trên mask-image, bức ảnh chính sẽ bị giấu càng nhiều.

  • Đối với Alpha masking, phần trong suốt của mask-image sẽ che bức ảnh chính: phần trong suốt càng nhiều trên mask-image, bức ảnh chính sẽ bị giấu càng nhiều.

Trong Chormoe ( phiên bản 51.0.2704.103, Win10), chi có alpha masking có thể sử dụng

Tại CSS, “alpha” và ‘’luminance” là những giá trị của thuộc tính “mask-type”

Đây là CSS để thêm mask vào ảnh nền trong trình duyệt Webkit:

CSS

#nightSkin{
    background-image:url('night.png');
    mask-type:alpha;
    /* transparent circle with remaining portion opaque */
    -webkit-mask-image:radial-gradient(circle at 45px 45px ,
    rgba(0,0,0,0) 45px,
    rgba(0,0,0,1) 45px);
}

/* When day skin selected */
#leftRadio:checked~#nightSkin{
    mask-type:alpha;
    /* opaque circle with remaining portion transparent */
    -webkit-mask-image:radial-gradient(circle at 405px 45px,
    rgba(0,0,0,1) 45px,
    rgba(0,0,0,0) 45px);
}

Tôi sử dụng thuộc tính “-webkit- mask-image” để tại phần ảnh che giấu ban đầu. Giá trị của nó là “radial- gradient()”.

Đối với lớp ngoài “Đêm”, tôi đã tạo 1 vòng tròn trong suốt, và tôi thực hiện phần còn lại với hình ảnh mờ đục.

Đối với lớp ngoài “Ngày”, tôi đã làm điều ngược lại: tạo 1 vòng tròn mờ đục và phần còn lại trong suốt

Mặc dù chưa được hỗ trợ trên các trình duyệt Webkit, tôi vãn thêm thuộc tính “mask-type” trong CSS để tham khảo trong tương lai.

6.jpg

Như bạn có thể thấy ở trên, phần viền của các vòng tròn không được mượt. Để giấu các cạnh thô, thêm một <div> sua lớp ngoài của khối hình tròn (cùng kích cỡ với hình tròn che giấu) với “box-shadow”.

Bóng tối sẽ che mờ các đường viền thô của vòng tròn

<div id="switchBtnOutline"></div>
#switchBtnOutline{
    width:90px;
    height:100%;
    border-radius:45px;
    box-shadow:0 0 2px 2px grey inset, 0 0 10px grey;
    pointer-events:none;
    position:absolute;
    margin:0;
}
/* Place #switchBtnOutline at the right end when day skin is selected */
#leftRadio:checked~#switchBtnOutline{
    right:0;
}

8.jpg

Bước 3b. Thêm mask (Dùng cho Firefox)

Thuộc tính “mask-image” thực ra là một thuộc tính nối dài, trong đó phần thuộc tính ngắn cho phép bạn chọn bức ảnh để thực hiện che giấu. Trong khi thuộc tính “mask-image” không được hỗ trợ tại trình duyệt Firefox còn “mask” thì có thể dụng tốt.

Giá trị “radial-gradient()” cũng không được hỗ trợ trên trình duyệt Firefox, nên để thay thế nó, hãy sử dụng ảnh SVG như một ảnh che giấu với kiểu “luminance”.

<svg>
    <rect x="0" y="0" width="450" height="90" fill="rgb(255,255,255)" />
<circle cx="45" cy="45" r="45" />
</svg>

Hình ảnh SVG phí trên giống như sự kết hợp của một hình chữ nhật màu trắng với hình tròn màu đen.

Thêm một SVG nưa mới hình chữ nhật màu đen và hình tròn màu trắng.

9.jpg

<svg>
    <defs>
        <!-- White rectangle + Black circle -->
        <mask  id="leftSwitchMask" >
            <rect x="0" y="0" width="450" height="90" fill="rgb(255,255,255)" />
            <circle cx="45" cy="45" r="45" />
        </mask >

        <!-- Black rectangle + White circle -->
        <mask  id="rightSwitchMask" >
            <rect x="0" y="0" width="450" height="90" />
            <circle cx="405" cy="45" r="45" fill="rgb(255,255,255)"/>
        </mask >
    </defs>
</svg>

Thay thế (hoặc kết hợp ) code CSS cho lớp ngoài “Đêm ” mà chúng ta đã sử dụng ở bước 3a. Và chúng ta đã hoàn thành.

Giờ chúng ta có 2 ảnh che giấu khác nhau (CSS gradient và SVG), 2 kiểu che giấu khác nhau (Alpha & Luminance), and đều được hỗ trợ bởi Firefox và Webkit.

#nightSkin{
    background-image: url('night.png');
    mask-type: luminance;
    mask:url(#leftSwitchMask);
}
#leftRadio:checked~#nightSkin{
    mask-type: luminance;
    mask:url(#rightSwitchMask);
}

Nếu bạn muốn xem toàn bộ code, hãy xem demo của bài hướng dẫn này trên Github