Chuyển mã SVG thành component React dùng được ngay trong dự án
Dán mã SVG xuất từ Figma, Illustrator hay tải về từ bộ icon, công cụ đổi toàn bộ thuộc tính gạch ngang sang camelCase, chuyển style dạng chuỗi thành object, dọn rác của trình chỉnh sửa rồi bọc lại thành component React hoàn chỉnh. Bạn chọn TypeScript hay JavaScript, function component hay forwardRef, có prop size và currentColor hay không, kết quả sinh lại ngay khi đổi tùy chọn.
Tính năng nổi bật
- Đổi toàn bộ thuộc tính gạch ngang sang camelCase: stroke-width, fill-rule, clip-rule, stroke-linecap, stroke-linejoin, stop-color, font-family, dominant-baseline và hàng chục thuộc tính khác
- Xử lý thuộc tính có dấu hai chấm: xlink:href thành xlinkHref, xml:space thành xmlSpace, xmlns:xlink thành xmlnsXlink
- Chuyển style dạng chuỗi thành object JSX, khóa camelCase, giá trị số thuần để nguyên dạng số còn lại bọc trong dấu nháy
- Thay màu cứng dạng hex, rgb, hsl hoặc tên màu ở fill và stroke bằng currentColor, giữ nguyên none và url tham chiếu gradient
- Bỏ width và height cứng ở thẻ svg gốc, giữ viewBox và gán width={size} height={size} theo prop size mặc định 24
- Dọn rác trình chỉnh sửa: xmlns:serif, inkscape, sodipodi, sketch, data-name và các id kiểu Layer_1, Path_123, chuỗi hex ngẫu nhiên
- Quét toàn văn bản tìm tham chiếu url(#id), href="#id", clip-path và mask trước khi xóa id để không làm vỡ gradient hay vùng cắt
- Chọn TypeScript hay JavaScript, function component hay forwardRef, bật tắt spread props, giữ hay bỏ thuộc tính data và aria
Vì sao không nên dán thẳng SVG vào file React
SVG là XML nên nó dùng quy ước đặt tên gạch ngang, còn JSX lại là cú pháp JavaScript nên thuộc tính phải viết camelCase. Dán thẳng một icon xuất từ Figma vào file tsx là bạn nhận ngay hàng loạt cảnh báo trong console về thuộc tính không hợp lệ, và tệ hơn là những thuộc tính đó bị React bỏ qua nên nét vẽ mất độ dày, đầu nét không bo tròn, quy tắc tô bị sai khiến hình có lỗ ở giữa. Thuộc tính style dạng chuỗi thì làm React ném lỗi thẳng chứ không chỉ cảnh báo. Sửa tay từng thuộc tính cho một icon đơn giản đã mất vài phút, còn với một bộ ba mươi icon thì đó là cả buổi làm việc nhàm chán và dễ sót. Chưa kể phần khó chịu hơn: tệp xuất từ phần mềm thiết kế luôn kèm theo một lớp rác gồm khai báo không gian tên riêng, thuộc tính data-name, và những id tự sinh kiểu Layer_1 hay Path_123. Đám id này vô hại khi mở một tệp SVG riêng lẻ, nhưng khi bạn nhúng năm icon cùng lúc vào một trang thì các id trùng nhau và trình duyệt chỉ nhận id đầu tiên, khiến gradient hoặc vùng cắt của những icon sau bị hỏng hoàn toàn.
Lợi ích khi sử dụng
- Không còn cảnh báo thuộc tính không hợp lệ trong console và không mất nét vẽ do React bỏ qua thuộc tính sai tên
- Icon đổi màu theo màu chữ của khối cha nhờ currentColor, không phải tạo bản sao cho từng trạng thái hover hay active
- Một component dùng ở mọi kích thước nhờ prop size, thay vì mỗi cỡ một tệp SVG riêng
- Spread props cho phép truyền className, onClick, aria-label và mọi thuộc tính SVG khác từ nơi gọi
- forwardRef giúp component dùng được với thư viện tooltip, popover và các thư viện cần đo vị trí phần tử
- Xóa id tự sinh trùng lặp nên nhúng nhiều icon cùng trang không làm hỏng gradient và vùng cắt của nhau
Cách chuyển SVG thành component React
- 1Lấy mã SVG: trong Figma chọn khung hình rồi bấm chuột phải và chọn sao chép dưới dạng SVG, hoặc mở tệp .svg bằng trình soạn thảo văn bản và chép toàn bộ nội dung.
- 2Dán vào ô nhập bên trái, khung xem trước bên dưới sẽ vẽ lại hình để bạn kiểm tra chắc chắn mình chép đủ chứ không thiếu phần nào.
- 3Đặt tên component vào ô tên, công cụ tự chuẩn hóa về PascalCase hợp lệ và hiển thị tên cuối cùng ngay bên dưới ô nhập.
- 4Chọn TypeScript hay JavaScript, function component hay forwardRef, rồi bật tắt các tùy chọn currentColor, prop size, spread props và giữ thuộc tính data cùng aria cho phù hợp với dự án.
- 5Đọc lại khối mã sinh ra, xem danh sách thuộc tính đã bị xóa để chắc chắn không mất gì cần thiết, rồi bấm nút copy và dán vào file component trong dự án.
Những thuộc tính SVG nào đổi tên, những thuộc tính nào phải giữ nguyên
Quy tắc chung của JSX là mọi thuộc tính gạch ngang chuyển sang camelCase, nhưng chỉ nhớ quy tắc thôi vẫn sai vì có một nhóm ngoại lệ quan trọng. Nhóm đổi tên gồm những cái gặp thường xuyên nhất trong icon: stroke-width thành strokeWidth, stroke-linecap thành strokeLinecap, stroke-linejoin thành strokeLinejoin, stroke-dasharray thành strokeDasharray, fill-rule thành fillRule, clip-rule thành clipRule, clip-path thành clipPath. Với gradient thì stop-color thành stopColor và stop-opacity thành stopOpacity. Với chữ trong SVG thì font-family thành fontFamily, font-size thành fontSize, text-anchor thành textAnchor, letter-spacing thành letterSpacing, dominant-baseline thành dominantBaseline. Một số ít gặp hơn nhưng vẫn xuất hiện trong tệp thật là marker-end thành markerEnd, paint-order thành paintOrder, shape-rendering thành shapeRendering, vector-effect thành vectorEffect. Nhóm có dấu hai chấm xử lý theo cách tương tự nhưng dễ quên: xlink:href thành xlinkHref, xml:space thành xmlSpace, xmlns:xlink thành xmlnsXlink. Nhóm ngoại lệ tuyệt đối không được đụng vào là viewBox và preserveAspectRatio, vốn đã viết hoa chữ cái giữa từ trong chính chuẩn SVG nên giữ y nguyên. Cùng nhóm giữ nguyên còn có mọi thuộc tính data và aria, vì React truyền thẳng chúng xuống DOM và đổi thành camelCase sẽ làm chúng biến mất khỏi thẻ. Cuối cùng, hai thuộc tính của HTML len vào SVG là class và for phải đổi thành className và htmlFor chứ không phải camelCase.
currentColor: cách làm icon tự đổi màu mà không cần sửa mã
currentColor là một giá trị đặc biệt trong SVG và CSS, nó có nghĩa là lấy đúng giá trị của thuộc tính color đang có hiệu lực tại phần tử đó. Khi bạn thay fill hoặc stroke cứng bằng currentColor, icon sẽ ăn theo màu chữ của khối cha, nên chỉ cần đặt một class màu chữ lên nút bấm là icon bên trong đổi màu theo, kể cả ở trạng thái hover, focus hay disabled, và kể cả khi trang chuyển sang chế độ tối. Đây là lý do gần như mọi thư viện icon phổ biến đều dựng icon bằng currentColor thay vì màu cố định. Nhưng có hai chỗ cần cân nhắc. Thứ nhất, chỉ nên thay khi icon là hình đơn sắc. Nếu bạn đang chuyển một logo nhiều màu hay một hình minh họa, việc gộp tất cả về một màu sẽ phá hỏng hình, khi đó hãy tắt tùy chọn này. Thứ hai, công cụ cố tình không đụng vào giá trị none và các giá trị dạng url tham chiếu gradient. Giữ none là bắt buộc vì rất nhiều icon dạng nét dùng fill none để hình không bị bôi đặc, đổi nó thành currentColor sẽ biến icon thành một mảng màu kín. Giữ url cũng bắt buộc vì đó là tham chiếu tới linearGradient hoặc radialGradient trong khối defs, thay bằng currentColor là mất hoàn toàn hiệu ứng chuyển màu. Với những icon vừa có nét vừa có mảng, hãy kiểm tra lại bằng khung xem trước sau khi bật tùy chọn.
Bỏ width và height cứng, giữ viewBox và dùng prop size
Thuộc tính viewBox khai báo hệ tọa độ bên trong của SVG, gồm bốn số là tọa độ góc trên trái cùng chiều rộng và chiều cao của vùng vẽ. Mọi số trong dữ liệu đường path đều tính theo hệ tọa độ này. Trong khi đó width và height ở thẻ svg chỉ nói kích thước hiển thị thực tế trên màn hình. Hai thứ độc lập nhau, và chính sự độc lập đó cho phép một tệp SVG duy nhất hiển thị ở mọi cỡ mà không vỡ nét. Vấn đề là phần mềm thiết kế luôn ghi kèm width và height bằng đúng kích thước khung lúc bạn xuất, ví dụ 48 pixel, nên nếu giữ nguyên thì icon luôn hiện ở 48 pixel dù bạn đặt class kích thước nào đi nữa, trừ khi ghi đè bằng CSS có độ ưu tiên cao hơn. Cách làm đúng của các thư viện icon là bỏ hẳn width và height khỏi mã, giữ viewBox, rồi nhận kích thước qua một prop. Công cụ này làm đúng như vậy: khi bật tùy chọn prop size, hai thuộc tính kích thước cứng bị gỡ khỏi thẻ svg gốc và thay bằng width bằng size cùng height bằng size, với giá trị mặc định 24 mà bạn có thể đổi. Nếu tệp gốc thiếu viewBox nhưng có width và height, công cụ tự dựng viewBox từ chính hai số đó để hình không bị mất tỉ lệ. Sau khi có prop size, bạn gọi cùng một component ở cỡ 16 cho nút nhỏ và cỡ 32 cho tiêu đề mà không cần thêm tệp nào.
forwardRef, spread props và chuyện dùng lại icon trong cả dự án
Một component icon chỉ vẽ được đúng một hình cố định thì gần như vô dụng khi dự án lớn lên. Điều làm nó dùng được ở mọi nơi là khả năng nhận thêm thuộc tính từ chỗ gọi. Bật tùy chọn spread props, công cụ sinh ra tham số nhận phần còn lại của props rồi rải chúng lên thẻ svg, nhờ vậy bạn truyền được className để đặt màu và khoảng cách, onClick để biến icon thành nút, aria-label và role khi icon mang nghĩa, hoặc aria-hidden khi icon chỉ trang trí. Ở bản TypeScript, kiểu props kế thừa SVGProps của SVGSVGElement nên trình soạn thảo gợi ý đầy đủ và báo lỗi ngay nếu bạn gõ sai tên thuộc tính. Tùy chọn forwardRef giải quyết một nhu cầu khác: nhiều thư viện giao diện cần lấy tham chiếu tới chính phần tử DOM để đo vị trí và kích thước, điển hình là tooltip, popover, menu thả xuống hay các thư viện kéo thả. Nếu component không chuyển tiếp ref, thư viện không có gì để bám vào và sẽ đặt sai vị trí hoặc báo lỗi. Khi bật forwardRef, mã sinh ra bọc component trong forwardRef với kiểu tham chiếu là SVGSVGElement, gán ref vào thẻ svg và đặt luôn displayName để React DevTools hiển thị đúng tên thay vì Anonymous. Nếu dự án của bạn chỉ dùng icon để trang trí và không cần ref, hãy để chế độ function component cho mã gọn hơn.
Id nào xóa được, id nào bắt buộc phải giữ khi dọn rác trình chỉnh sửa
Đây là phần dễ làm hỏng hình nhất nếu dọn ẩu. Tệp xuất từ Figma, Illustrator hay Inkscape luôn kèm những id tự sinh vô nghĩa như Layer_1, svg_2, Path_123, Group_12, Rectangle_9, hoặc chuỗi hex và uuid dài. Chúng làm mã dài ra vô ích, nhưng nguy hiểm thật sự nằm ở chỗ khác: id trong SVG có phạm vi toàn tài liệu chứ không giới hạn trong từng thẻ svg. Khi bạn nhúng năm icon cùng xuất từ Figma vào một trang, cả năm đều mang id Layer_1 và trình duyệt chỉ nhận cái đầu tiên, khiến gradient hay vùng cắt của bốn icon sau trỏ nhầm hoặc trỏ vào hư không. Ngược lại, có những id tuyệt đối không được xóa vì chúng đang được tham chiếu: gradient được gọi qua fill bằng url thăng id, vùng cắt gọi qua clip-path bằng url thăng id, mặt nạ gọi qua mask, bộ lọc gọi qua filter, và thẻ use trỏ tới hình qua href thăng id. Xóa nhầm một trong số đó là icon biến mất hoặc mất màu. Vì vậy công cụ quét toàn bộ văn bản tìm mọi chuỗi bắt đầu bằng dấu thăng trước khi quyết định, id nào xuất hiện trong danh sách tham chiếu thì giữ lại nguyên vẹn dù trông có ngẫu nhiên đến đâu, chỉ id vừa khớp mẫu tự sinh vừa không bị ai tham chiếu mới bị gỡ. Danh sách thuộc tính đã xóa hiện ngay dưới khối mã để bạn tự kiểm tra lại.
Ranh giới với các công cụ SVG khác: khi nào dùng cái nào
Trên site có vài công cụ nghe na ná nhau nhưng giải quyết những việc khác hẳn, chọn nhầm là mất thời gian. Công cụ chuyển HTML sang JSX làm việc đổi cú pháp chung cho mọi thẻ HTML, phù hợp khi bạn bê nguyên một khối giao diện từ mẫu tĩnh sang React. Nó không biết gì về đặc thù của icon, nên không bỏ width và height cứng, không thay màu bằng currentColor, không sinh prop size, không bọc forwardRef và không dọn rác của phần mềm thiết kế. Trang bạn đang xem sinh hẳn một component hoàn chỉnh với đầy đủ những thứ đó. Công cụ tối ưu SVG thì lại làm việc ở tầng dữ liệu hình: rút gọn đường path, cắt bớt số thập phân thừa, gộp nhóm, xóa thẻ rỗng, và đầu ra vẫn là một tệp SVG nhẹ hơn chứ không phải mã React. Hai công cụ này bổ sung cho nhau và thứ tự hợp lý là tối ưu trước rồi sinh component sau, vì như vậy mã component cũng ngắn theo. Công cụ chuyển SVG sang CSS đi hướng thứ ba: nó mã hóa hình thành chuỗi data URI để đặt vào background-image, hợp với icon nền của nút bấm hay dấu đầu dòng danh sách, nhưng đổi lại bạn mất khả năng đổi màu bằng currentColor và không truyền được props hay ref. Quy tắc chọn đơn giản: hình nằm trong cây React và cần đổi màu theo trạng thái thì dùng component, hình chỉ là nền trang trí tĩnh thì dùng CSS.
Câu hỏi thường gặp (FAQ)
Vì sao dán SVG thẳng vào file React lại báo lỗi hoặc mất nét?
Vì SVG viết thuộc tính kiểu gạch ngang còn JSX bắt buộc camelCase. React bỏ qua những thuộc tính không nhận ra nên stroke-width, stroke-linecap và fill-rule mất tác dụng, khiến nét mỏng đi, đầu nét vuông và hình có lỗ ở giữa. Riêng style dạng chuỗi thì React ném lỗi thẳng vì nó chỉ nhận object.
currentColor hoạt động thế nào và khi nào không nên bật?
currentColor lấy đúng giá trị thuộc tính color đang có hiệu lực, nên icon ăn theo màu chữ của khối cha và tự đổi khi hover hay khi chuyển chế độ tối. Đừng bật khi bạn chuyển logo nhiều màu hoặc hình minh họa, vì gộp tất cả về một màu sẽ phá hỏng hình.
Vì sao công cụ không đổi fill="none" thành currentColor?
Vì rất nhiều icon dạng nét dùng fill none để phần trong hình không bị bôi đặc, chỉ còn đường viền. Đổi none thành currentColor sẽ biến icon thành một mảng màu kín, mất hoàn toàn hình dạng. Tương tự, giá trị url trỏ tới gradient cũng được giữ nguyên.
Bỏ width và height cứng có làm icon mất tỉ lệ không?
Không, miễn là viewBox còn nguyên. viewBox khai báo hệ tọa độ bên trong, còn width và height chỉ nói kích thước hiển thị. Nếu tệp gốc thiếu viewBox nhưng có width và height, công cụ tự dựng viewBox từ chính hai số đó nên tỉ lệ vẫn đúng.
Khi nào cần chọn forwardRef thay vì function component?
Khi component icon phải chuyển tiếp ref tới phần tử DOM cho các thư viện cần đo vị trí và kích thước như tooltip, popover, menu thả xuống hay thư viện kéo thả. Nếu icon chỉ để trang trí và không ai gắn ref vào, chọn function component cho mã gọn hơn.
Vì sao nhúng nhiều icon cùng trang lại bị hỏng gradient?
Vì id trong SVG có phạm vi toàn tài liệu chứ không giới hạn trong từng thẻ svg. Nhiều icon cùng xuất từ Figma đều mang id Layer_1 hoặc clip0, trình duyệt chỉ nhận cái đầu tiên nên các icon sau trỏ nhầm. Xóa id thừa như công cụ này làm chính là cách tránh xung đột.
Công cụ có xóa nhầm id đang được dùng cho clip-path hay mask không?
Không. Trước khi quyết định, công cụ quét toàn bộ văn bản tìm mọi chuỗi bắt đầu bằng dấu thăng, gồm url trong fill, href của thẻ use, clip-path, mask và filter. Id nào nằm trong danh sách tham chiếu thì giữ nguyên, chỉ id vừa khớp mẫu tự sinh vừa không ai tham chiếu mới bị gỡ.
Tôi muốn giữ aria-hidden và data-testid thì làm sao?
Bật công tắc giữ lại thuộc tính data và aria trong khối tùy chọn. Khi bật, chúng được giữ nguyên dạng gạch ngang chứ không đổi camelCase, vì React truyền thẳng nhóm này xuống DOM. Riêng data-name của Figma và Illustrator luôn bị xóa vì đó là rác của phần mềm thiết kế.
Tool này khác gì công cụ chuyển HTML sang JSX?
Công cụ HTML sang JSX chỉ đổi cú pháp chung cho mọi thẻ HTML. Trang này xử lý riêng đặc thù SVG: giữ viewBox nhưng bỏ width và height cứng, thay màu cứng bằng currentColor, sinh prop size, bọc forwardRef và dọn rác của Figma cùng Illustrator, rồi trả về một component hoàn chỉnh chứ không chỉ đoạn markup.
Nên chạy công cụ tối ưu SVG trước hay sau khi sinh component?
Trước. Bộ tối ưu làm việc trên dữ liệu hình, rút gọn đường path, cắt số thập phân thừa và gộp nhóm, nên chạy nó xong rồi mới dán vào đây sẽ cho component ngắn hơn hẳn. Chạy ngược lại thì bạn phải bóc mã React ra để đưa về SVG, mất công vô ích.
Tên component tôi gõ tiếng Việt có dấu thì sao?
Công cụ tự bỏ dấu, đổi chữ đ thành d, cắt mọi ký tự không phải chữ và số, rồi ghép lại thành PascalCase hợp lệ. Nếu tên bắt đầu bằng chữ số, công cụ thêm tiền tố Icon vì tên component JavaScript không được mở đầu bằng số. Tên cuối cùng hiện ngay dưới ô nhập.
Prop size mặc định 24 có đổi được không?
Được. Khi bật tùy chọn prop size, ô nhập giá trị mặc định hiện ra và bạn gõ số nào cũng được, chẳng hạn 16 cho icon trong nút nhỏ hay 32 cho icon tiêu đề. Con số này chỉ là giá trị mặc định, ở nơi gọi bạn vẫn truyền size khác cho từng chỗ.
Mã SVG của tôi có được gửi lên máy chủ không?
Không. Toàn bộ việc chuyển đổi chạy bằng JavaScript ngay trong trình duyệt của bạn, kể cả khung xem trước hình gốc. Không có lệnh gọi mạng, không lưu lại nội dung bạn dán và không cần đăng ký tài khoản, nên dùng được cả với icon nội bộ chưa công bố.
Công cụ có xử lý được animation và filter trong SVG không?
Có ở mức đổi tên thuộc tính và giữ nguyên cấu trúc, gồm các thẻ animate, animateTransform và nhóm thẻ bộ lọc như feGaussianBlur hay feColorMatrix. Riêng CSS animation viết trong thẻ style bên trong SVG thì bạn nên tách ra file CSS riêng vì JSX không nhận trực tiếp khối CSS đó.
Vì sao khung xem trước hiện hình nhưng khối mã lại báo không tìm thấy thẻ svg?
Trường hợp này hiếm và thường do bạn dán một thẻ img trỏ tới tệp .svg thay vì dán chính mã SVG. Trình duyệt vẽ được ảnh nhưng bộ chuyển đổi không có mã nguồn để làm việc. Hãy mở tệp .svg bằng trình soạn thảo văn bản rồi chép toàn bộ nội dung bên trong.
Từ khóa liên quan
- chuyển svg sang react component
- svg to react component
- svg to jsx
- chuyển svg thành icon react
- svg camelcase jsx
- stroke-width strokeWidth react
- fill-rule fillRule jsx
- xlink:href xlinkHref react
- currentcolor svg react
- icon react đổi màu theo chữ
- prop size cho icon react
- viewbox svg là gì
- bỏ width height svg giữ viewbox
- forwardref svg react
- svgprops svgsvgelement typescript
- spread props svg react
- xóa id layer_1 svg figma
- dọn rác svg illustrator
- svg trùng id gradient lỗi
- export svg figma sang react
- tạo thư viện icon react
- component icon typescript
- style svg sang object jsx
- công cụ chuyển svg sang react online
