Nhúng SVG vào CSS bằng data URI: cách encode đúng và giới hạn cần biết
Công cụ dán code SVG vào và nhận ngay chuỗi background-image dạng data URI, có sẵn hai kiểu mã hóa là URL encoded và Base64. Bản xem trước đặt hình lên ba nền trắng, xám và đen để bạn kiểm tra phần trong suốt trước khi dán vào file CSS. Toàn bộ việc mã hóa chạy trong trình duyệt, code SVG không được gửi đi đâu.
Tính năng nổi bật
- Sinh chuỗi url("data:image/svg+xml,...") theo kiểu URL encoded, gọn hơn Base64
- Sinh song song bản Base64 cho trường hợp cần bám sát chuẩn data URI cũ
- Tự chèn thuộc tính xmlns nếu code SVG dán vào bị thiếu, tránh lỗi không hiện hình
- Đổi dấu nháy kép trong SVG thành nháy đơn để không phá vỡ chuỗi CSS bao ngoài
- Mã hóa các ký tự phá cú pháp CSS: dấu phần trăm, dấu thăng, dấu ngoặc nhọn, dấu lớn nhỏ
- Gộp mọi khoảng trắng và xuống dòng thành một dấu cách, giảm độ dài chuỗi
- Xem trước hình gốc và xem trước trên ba nền trắng, xám, đen để soi vùng trong suốt
- Xuất sẵn một khối CSS class kèm background-repeat, background-position và background-size
Vì sao vẫn cần nhúng SVG vào CSS thay vì để file rời
Một biểu tượng 400 byte để thành file rời vẫn tốn một vòng yêu cầu mạng đầy đủ: phân giải DNS nếu khác tên miền, bắt tay kết nối, chờ phản hồi. Với chục biểu tượng nhỏ trong giao diện, phần chi phí kết nối lớn hơn nhiều lần bản thân dữ liệu. Nhúng thẳng vào CSS thì hình đi cùng file định kiểu, đã có mặt ngay tại thời điểm trình duyệt tính toán bố cục, nên không có cảnh khung trống nhấp nháy rồi mới hiện biểu tượng. Cách này cũng gọn khi bàn giao: một file CSS duy nhất, không kèm thư mục ảnh dễ thất lạc khi đổi hệ thống. Đổi lại, chuỗi data URI không được nén tốt như file nhị phân riêng và không cache độc lập, nên chỉ nên dùng cho hình nhỏ, dùng lặp lại nhiều nơi và ít khi thay đổi.
Lợi ích khi sử dụng
- Bớt một lượt tải mạng cho mỗi biểu tượng nhỏ, hữu ích nhất khi giao diện có nhiều icon
- Hình xuất hiện cùng lúc với CSS nên không có khoảng nhấp nháy trống trước khi icon hiện
- Thấy ngay hình trên nền sáng và nền tối, phát hiện sớm icon màu trắng biến mất trên nền trắng
- Chuỗi URL encoded vẫn đọc được nên khi lỗi hiển thị bạn dò được ngay trong file CSS
- Bản thiết kế của khách không rời khỏi máy vì việc mã hóa chạy hoàn toàn trong trình duyệt
Cách chuyển SVG sang CSS background-image
- 1Mở file SVG bằng trình soạn thảo văn bản hoặc sao chép trực tiếp từ công cụ thiết kế, rồi dán toàn bộ thẻ svg vào ô nhập bên trái.
- 2Nếu chỉ muốn thử nhanh, bấm nút Ví dụ để công cụ nạp sẵn một biểu tượng đồng hồ đơn giản.
- 3Nhìn sang khung xem trước: hàng ba ô nền trắng, xám và đen cho biết hình có bị chìm trên nền nào không.
- 4Chọn bản URL encoded nếu muốn chuỗi ngắn và còn đọc được, hoặc bản Base64 nếu cần một chuỗi thuần ASCII không chứa ký tự đặc biệt.
- 5Bấm sao chép khối CSS class rồi dán vào file định kiểu, đổi tên class và chỉnh lại kích thước phần tử cho khớp với khung hình của SVG.
Vì sao phải mã hóa và mã hóa những ký tự nào
Chuỗi data URI nằm bên trong dấu ngoặc của hàm url() trong CSS, nên mọi ký tự có ý nghĩa với bộ phân tích cú pháp CSS đều phải được che đi. Dấu thăng là thủ phạm phổ biến nhất: mọi mã màu dạng ba hoặc sáu chữ số đều bắt đầu bằng dấu thăng, mà trong data URI dấu này đánh dấu phần định danh mảnh nên trình duyệt sẽ cắt bỏ toàn bộ phần phía sau, kết quả là hình biến mất hoàn toàn chứ không phải sai màu. Công cụ đổi nó thành phần trăm hai ba. Dấu lớn và dấu nhỏ bao quanh mọi thẻ SVG được đổi thành phần trăm ba C và phần trăm ba E. Dấu ngoặc nhọn bị đổi vì nó là dấu mở đóng khối trong CSS. Dấu phần trăm phải được mã hóa trước tiên, nếu không những dấu phần trăm do chính quá trình mã hóa sinh ra sẽ bị mã hóa chồng lên. Ngoài ra công cụ đổi mọi dấu nháy kép trong thuộc tính SVG thành nháy đơn, vì chuỗi bên ngoài đang dùng nháy kép, và gộp xuống dòng thành một dấu cách để rút ngắn chuỗi.
Vì sao thiếu xmlns là hình không hiện
Khi SVG nằm trực tiếp trong HTML, trình duyệt biết ngay đó là đồ họa vector nhờ ngữ cảnh của tài liệu, nên đoạn mã thiếu thuộc tính xmlns vẫn hiển thị bình thường. Nhưng khi cùng đoạn mã đó được đưa vào data URI với kiểu nội dung image cộng svg cộng xml, trình duyệt xử lý nó như một tài liệu XML độc lập. Bộ phân tích XML bắt buộc thẻ gốc phải khai báo không gian tên, và nếu thiếu thì tài liệu bị coi là không hợp lệ, kết quả là ô nền trống trơn mà bảng điều khiển thường không báo lỗi rõ ràng. Đây là lý do rất nhiều người dán SVG xuất từ công cụ thiết kế vào CSS rồi không hiểu vì sao trong HTML thì chạy còn trong CSS thì mất. Công cụ này kiểm tra chuỗi có chứa xmlns hay không, nếu không thì chèn thêm ngay sau thẻ mở svg. Bạn vẫn nên tự xác nhận lại khi sao chép chuỗi từ nguồn khác, đặc biệt khi SVG có dùng thêm không gian tên xlink cho thẻ use.
URL encoded và Base64: chọn theo tình huống nào
Bản URL encoded chỉ thay thế một nhóm ký tự nhỏ nên độ dài chuỗi gần bằng độ dài SVG gốc, phần lớn nội dung vẫn đọc được bằng mắt. Điều này quan trọng khi gỡ lỗi: mở file CSS ra bạn còn thấy được thẻ path, thấy được mã màu, sửa trực tiếp một giá trị mà không cần mã hóa lại. Bản Base64 thì luôn phình ra khoảng một phần ba so với dữ liệu gốc vì cứ ba byte được biểu diễn bằng bốn ký tự, và kết quả là một khối ký tự hoàn toàn không đọc được. Bù lại nó không chứa ký tự nào có thể gây xung đột cú pháp, nên an toàn khi chuỗi phải đi qua nhiều lớp xử lý như bộ nén CSS, bộ tiền xử lý hoặc hệ thống mẫu tự thay thế ký tự. Với dự án web hiện nay, bản URL encoded là lựa chọn mặc định hợp lý. Chỉ chuyển sang Base64 khi bạn gặp lỗi lạ trong chuỗi công cụ dựng, hoặc khi hệ thống đích yêu cầu dữ liệu thuần ASCII.
Đổi màu icon nhúng trong CSS bằng mask-image
Hạn chế lớn nhất của background-image là hình đã bị đóng băng: mọi giá trị fill và stroke nằm bên trong chuỗi, thuộc tính color của phần tử cha không tác động được, và từ khóa currentColor trong SVG mất tác dụng vì không còn tài liệu chủ để tham chiếu. Nếu SVG bạn dán vào dùng stroke bằng currentColor như ví dụ mẫu của công cụ, đường nét sẽ hiện màu đen mặc định chứ không theo màu chữ. Cách xử lý cho biểu tượng một màu là dùng mask-image thay cho background-image: đặt background-color bằng currentColor rồi lấy chính chuỗi data URI làm mặt nạ, kèm mask-repeat no-repeat, mask-position center và mask-size contain. Khi đó hình dạng lấy từ SVG còn màu lấy từ CSS, nên một chuỗi dùng được cho mọi trạng thái hover, active hay giao diện tối. Safari cần thêm bản có tiền tố webkit. Với biểu tượng nhiều màu thì cách này không dùng được, bạn phải tạo nhiều bản SVG khác nhau.
Giới hạn thật của cách nhúng này
Hàm btoa dùng để tạo bản Base64 chỉ nhận được ký tự trong bảng mã Latin-1. Nếu SVG của bạn có thẻ text chứa tiếng Việt có dấu hoặc bất kỳ ký tự Unicode nào ngoài phạm vi đó, hàm sẽ ném lỗi và ô Base64 hiện trống; lúc đó hãy dùng bản URL encoded, hoặc tốt hơn là chuyển chữ thành đường path trong công cụ thiết kế trước khi xuất. Hình nhúng trong CSS cũng hoàn toàn vô hình với trình đọc màn hình, nên chỉ dùng cho phần trang trí; biểu tượng mang nghĩa như nút đóng hay nút xóa phải đặt SVG trực tiếp trong HTML kèm nhãn phù hợp. Hoạt ảnh bên trong SVG, dù viết bằng SMIL hay CSS, đều không chạy khi hình đóng vai trò ảnh nền. Cuối cùng, chuỗi data URI nằm trong file CSS nên không được cache riêng: sửa một biểu tượng là toàn bộ file CSS phải tải lại. Vì vậy hãy tối ưu SVG trước, và giữ mức nhúng cho hình nhỏ vài kilobyte.
Câu hỏi thường gặp (FAQ)
Vì sao SVG hiện trong HTML nhưng dán vào CSS thì mất tiêu?
Nguyên nhân hay gặp nhất là thiếu thuộc tính xmlns. Trong data URI, đoạn mã được đọc như một tài liệu XML riêng nên bắt buộc phải khai báo không gian tên, còn trong HTML thì không cần. Nguyên nhân thứ hai là dấu thăng của mã màu chưa được mã hóa, khiến trình duyệt cắt bỏ phần chuỗi phía sau.
Vì sao ô Base64 lại trống trong khi ô URL encoded vẫn có kết quả?
Vì hàm tạo Base64 của trình duyệt chỉ nhận ký tự thuộc bảng mã Latin-1. Nếu SVG của bạn chứa chữ tiếng Việt có dấu, ký hiệu đặc biệt hay emoji trong thẻ text, hàm sẽ báo lỗi và công cụ trả về chuỗi rỗng. Hãy dùng bản URL encoded, hoặc chuyển phần chữ thành đường path trước khi xuất file.
Nên chọn URL encoded hay Base64?
Mặc định nên chọn URL encoded vì chuỗi ngắn hơn và vẫn đọc được nên dễ sửa trực tiếp trong file CSS. Base64 luôn dài hơn khoảng một phần ba do cách biểu diễn ba byte thành bốn ký tự. Chỉ chuyển sang Base64 khi chuỗi phải đi qua hệ thống xử lý làm hỏng ký tự phần trăm hoặc yêu cầu dữ liệu thuần ASCII.
Icon của tôi dùng stroke currentColor, sao dán vào CSS lại thành màu đen?
Vì trong ảnh nền, SVG không còn tài liệu chủ để lấy giá trị color nên currentColor rơi về màu mặc định. Cách xử lý là ghi cứng mã màu vào SVG trước khi mã hóa, hoặc dùng mask-image kết hợp background-color bằng currentColor để hình dạng lấy từ SVG còn màu lấy từ CSS.
SVG bao nhiêu là quá lớn để nhúng vào CSS?
Không có ngưỡng cứng, nhưng vài kilobyte là mức hợp lý cho biểu tượng và họa tiết nền. Vượt quá mức đó, chuỗi làm phình file CSS vốn nằm trên đường dẫn hiển thị quan trọng, và mỗi lần sửa hình là người dùng phải tải lại toàn bộ CSS. Minh họa lớn nên để thành file rời và cho tải trễ.
Có cần tối ưu SVG trước khi chuyển không?
Rất nên. File xuất từ công cụ thiết kế thường kèm siêu dữ liệu, chú thích, thuộc tính id thừa và tọa độ nhiều chữ số thập phân không cần thiết. Dọn những thứ đó thường giảm được đáng kể độ dài chuỗi mà hình không đổi. Làm gọn trước rồi mới mã hóa, vì sau khi mã hóa thì chuỗi khó chỉnh hơn nhiều.
Hoạt ảnh trong SVG có chạy khi nhúng vào CSS không?
Không. Khi đóng vai trò ảnh nền, SVG được xử lý như một hình tĩnh nên cả hoạt ảnh viết bằng SMIL lẫn hoạt ảnh viết bằng CSS bên trong file đều không chạy, và mã JavaScript bên trong cũng không thực thi. Muốn có hoạt ảnh, bạn phải đặt SVG trực tiếp trong HTML.
Vì sao khung xem trước lại đặt hình lên ba nền khác nhau?
Để lộ ra hai lỗi hay gặp. Thứ nhất là biểu tượng chỉ có nét viền màu trắng sẽ biến mất hoàn toàn trên nền sáng. Thứ hai là vùng lẽ ra trong suốt nhưng thực chất được tô trắng, chỉ nhìn thấy khi đặt lên nền đen. Kiểm tra sớm ở đây đỡ hơn nhiều so với phát hiện khi bật giao diện tối.
Đặt kích thước cho biểu tượng nhúng thế nào cho đúng?
Ảnh nền không tự tạo kích thước cho phần tử, nên bạn phải đặt chiều rộng và chiều cao cho chính phần tử đó. Sau đó dùng background-size contain để hình vừa khung mà giữ tỷ lệ, hoặc cover nếu chấp nhận bị cắt. Nhớ giữ tỷ lệ khung trùng với thuộc tính viewBox của SVG để hình không bị lệch.
Chuỗi data URI có ảnh hưởng tới tốc độ tải trang không?
Có cả hai chiều. Nó tiết kiệm một vòng yêu cầu mạng cho mỗi hình, rất đáng với biểu tượng nhỏ. Nhưng nó cũng làm file CSS to ra, mà CSS lại chặn quá trình hiển thị. Nhúng vài biểu tượng nhỏ thì có lợi, nhúng hàng chục hình lớn thì lợi bất cập hại.
Trình đọc màn hình có đọc được biểu tượng nhúng kiểu này không?
Không. Mọi thứ đặt qua background-image đều bị bỏ qua trong cây trợ năng, kể cả khi SVG có thẻ title bên trong. Vì vậy chỉ dùng cách này cho hình trang trí. Với biểu tượng mang thông tin, hãy đặt SVG trực tiếp trong HTML và gắn nhãn văn bản, hoặc thêm chữ ẩn dành riêng cho trình đọc màn hình.
Code SVG tôi dán vào có bị gửi lên máy chủ không?
Không. Việc thay thế ký tự và tạo chuỗi Base64 đều chạy bằng JavaScript ngay trong trình duyệt, không có bước tải lên. Bạn có thể dùng với bộ nhận diện thương hiệu của khách hoặc tài sản thiết kế chưa công bố mà không lo lộ ra ngoài.
Từ khóa liên quan
- svg to css
- chuyển svg sang css
- svg data uri
- svg background image css
- inline svg trong css
- svg url encode
- svg sang base64
- data uri svg online
- nhúng svg vào css
- css background svg online
- svg to css converter
- encode svg cho css
- svg mask image css
- đổi màu svg trong css
- svg không hiện trong css
- lỗi xmlns svg data uri
- tối ưu icon svg cho web
- giảm http request icon svg
- svg to css online free
- công cụ chuyển svg sang css miễn phí
