Dùng CSS xử lý triệt để vấn đề tràn văn bản
Sử dụng các thuộc tính CSS thế nào để ngắt văn bản hiệu quả? Bài viết này sẽ tổng hợp các tình huống sử dụng và mẹo hữu ích giúp lập trình viên đưa ra lựa chọn chính xác hơn.
Tràn văn bản là một vấn đề phổ biến khi thiết kế giao diện, đặc biệt với các nội dung dài như bài blog hoặc bình luận. Nếu không được xử lý, điều này có thể ảnh hưởng đến trải nghiệm người dùng vì văn bản có thể chồng lấn lên các thành phần khác, gây rối mắt và khó đọc. Ngoài ra, các từ quá dài không được tự động ngắt dòng có thể làm vỡ bố cục, gia tăng chỉ số dịch chuyển bố cục (CLS – Cumulative Layout Shift), khiến giao diện trở nên kém ổn định.
Mặc dù các trình duyệt hiện nay đều hỗ trợ tự động ngắt dòng khi văn bản vượt quá kích thước cho phép, hay còn gọi là cơ chế ngắt dòng mềm (soft line break), nhưng cơ chế mặc định này vẫn chưa đủ để xử lý triệt để các tình huống tràn văn bản.
Chính vì vậy, các thuộc tính CSS như overflow-wrap
, word-break
và hyphens
ra đời nhằm giúp lập trình viên kiểm soát việc ngắt dòng một cách hiệu quả và linh hoạt hơn. Trong bài viết này, hãy cùng mình tìm hiểu sâu hơn về chức năng, cách sử dụng và sự khác biệt giữa 3 thuộc tính này nhé.
overflow-wrap
Thuộc tính overflow-wrap
giúp kiểm soát cách ngắt dòng của văn bản bằng cách cố gắng giữ nguyên toàn vẹn của một từ. Khi một từ không đủ chỗ trên dòng hiện tại, trình duyệt sẽ ưu tiên đưa toàn bộ từ đó xuống dòng tiếp theo. Tuy nhiên, nếu từ vẫn vượt quá kích thước của dòng mới, trình duyệt sẽ tự động ngắt từ tại vị trí bị tràn để tránh phá vỡ bố cục.
Thuộc tính này hỗ trợ 3 giá trị:
- overflow-wrap: normal
- overflow-wrap: anywhere
- overflow-wrap: break-word
Trong đó:
normal
: Không thay đổi cách ngắt dòng, trình duyệt sẽ tuân theo quy tắc mặc định.anywhere
vàbreak-word
: Cả hai giá trị này hoạt động tương tự nhau và chỉ khác nhau ở một điểm.
anywhere
vs. break-word
Cả anywhere
và break-word
đều giúp trình duyệt tự động ngắt từ khi không thể hiển thị đầy đủ trên dòng hiện tại. Nếu vẫn không đủ chỗ ở dòng mới, trình duyệt tiếp tục ngắt tại vị trí kí tự bị tràn.
Sự khác biệt giữa hai giá trị này nằm ở cách chúng ảnh hưởng đến kích thước nội tại (intrinsic size) của phần tử (element) khi sử dụng với width: min-content
hay trong layout flex. Khi tính kích thước nội tại tối thiểu (min-content intrinsic size), hành vi ngắt dòng sẽ không được xem xét để tính vào khi sử dụng giá trị break-word
nhưng anywhere
thì lại được.
Trong trường hợp width: min-content
, anywhere
đã ngắt dòng sau chỉ 1 hoặc 2 kí tự. Mặc dù hành vi này có vẻ bất thường, nhưng nó phản ánh đúng cách anywhere
hoạt động. Khi sử dụng với width: min-content
, mục tiêu là đạt kích thước nhỏ nhất có thể mà không làm tràn nội dung. Do đó, anywhere
sẽ cố gắng ngắt nhiều nhất có thể để đáp ứng yêu cầu này. Nhưng đối với break-word
, văn bản bị tràn sẽ không được ngắt vì giá trị này đã bị phớt lờ đi.
Tương tự, trong bố cục flex, trình duyệt cũng dựa trên kích thước nội tại tối thiểu để phân bố không gian. Do đó, break-word
không có ảnh hưởng trong trường hợp này, trong khi anywhere
vẫn có thể giúp ngắt từ linh hoạt. Mình sẽ để đường dẫn đến bài viết giải thích đầy đủ hơn ở đây.
overflow-wrap
Lưu ý khi dùng Tóm lại, thuộc tính overflow-wrap
đặc biệt phù hợp trong các trường hợp cần ưu tiên khả năng đọc của người dùng, chẳng hạn như bài blog, truyện chữ, mô tả sản phẩm,... Đây là những nơi chứa lượng lớn văn bản, đòi hỏi người dùng phải đọc liên tục, nên việc giữ nguyên cấu trúc từ giúp việc theo dõi nội dung trở nên dễ dàng hơn.
Bên cạnh đó, khi sử dụng overflow-wrap
với các giá trị anywhere
và break-word
, cần lưu ý đến sự khác biệt giữa chúng, nhất là khi kết hợp với các thuộc tính ảnh hưởng đến kích thước nội tại tối thiểu như flex
hoặc width: min-content
. Giá trị anywhere
sẽ được trình duyệt tính đến trong quá trình xác định kích thước tối thiểu, trong khi break-word
thì không. Điều này có thể dẫn đến một số hành vi ngoài ý muốn trong bố cục nếu không chú ý kỹ.
word-break
Khác với overflow-wrap
, thuộc tính word-break
sẽ ngắt dòng ngay tại kí tự gây tràn, thay vì cố gắng bảo toàn toàn bộ từ. Điều này đặc biệt hữu ích trong những trường hợp không muốn xuất hiện khoảng trống quá lớn giữa các từ hoặc phần tử, chẳng hạn như khi hiển thị nhãn cho các radio button dưới đây.
Ngoài ra, word-break
cũng được thiết kế để hỗ trợ cho các ngôn ngữ thuộc nhóm CJK (Trung, Nhật, Hàn), vốn có cách ngắt dòng khác biệt so với các ngôn ngữ dùng bảng chữ cái Latinh.
Thuộc tính này có ba giá trị chính:
- word-break: normal
- word-break: break-all
- word-break: keep-all
Với normal
, trình duyệt sẽ dùng cơ chế mặc định. Ở đây mình sẽ chỉ nói về 2 giá trị là break-all
và keep-all
. Ngoài ra, word-break
cũng có một giá trị khác đó là break-word
nhưng nó đã bị lỗi thời.
break-all
break-all
cho phép trình duyệt ngắt từ ngay tại bất kỳ kí tự nào bị tràn. Tuy nhiên, giá trị này chỉ ảnh hưởng đến các kí tự không thuộc nhóm CJK. Đối với văn bản CJK, trình duyệt vẫn áp dụng quy tắc ngắt dòng mặc định.
keep-all
keep-all
có tác động ngược lại, chỉ ảnh hưởng đến các kí tự thuộc nhóm CJK, đảm bảo chúng luôn được giữ nguyên trên cùng một dòng, ngay cả khi gây tràn nội dung. Còn với các kí tự không thuộc nhóm này, chúng sẽ được xử lý theo giá trị normal
, tức là ngắt dòng dựa trên quy tắc mặc định của trình duyệt.
word-break
Lưu ý khi dùng Như vậy, so với thuộc tính overflow-wrap
, word-break
không quan tâm tính toàn vẹn mà sẽ ngắt từ ngay tại vị trí bị tràn. Cách xử lý này phù hợp trong các tình huống mà việc bảo toàn từ không quá quan trọng, nơi cần tiết kiệm không gian và tránh khoảng trống lớn giữa các từ, chẳng hạn như hiển thị các chuỗi không thể đọc được như ID, đường dẫn URL, nút (button) nhỏ có kèm biểu tượng, …
Khi sử dụng hai giá trị break-all
và keep-all
, cần lưu ý đến nhóm ngôn ngữ mà chúng ảnh hưởng đến. Cụ thể, break-all
chỉ tác động đến các ngôn ngữ không thuộc nhóm CJK, còn keep-all
chỉ có hiệu lực đối với ngôn ngữ thuộc nhóm CJK. Đối với các ngôn ngữ không bị ảnh hưởng, trình duyệt sẽ quay về sử dụng quy tắc ngắt dòng mặc định của nó.
hyphens
Đây là thuộc tính cuối cùng có thể dùng để trình duyệt thực hiện ngắt dòng bằng cách dựa vào kí tự dấu nối (mặc định là -). Một điểm quan trọng của hyphens
là hỗ trợ nhiều ngôn ngữ khác nhau, dựa trên thuộc tính lang
của phần tử.
Các giá trị chính của hyphens
bao gồm:
- hyphens: auto
- hyphens: manual
auto
Khi sử dụng hyphens: auto
, trình duyệt sẽ dựa vào thuộc tính lang
để tự động xác định quy tắc ngắt từ và vị trí thêm dấu nối (còn gọi là hyphenation character). Mỗi ngôn ngữ có bộ quy tắc ngắt từ riêng, vì vậy kết quả hiển thị sẽ khác nhau tùy theo ngôn ngữ được khai báo. Ví dụ, với lang="en"
(tiếng Anh) và lang="de"
(tiếng Đức), cùng một từ có thể được ngắt tại các vị trí khác nhau do sự khác biệt trong bộ quy tắc ngắt từ của từng ngôn ngữ.
manual
Giá trị hyphens: manual
cho phép người dùng tự xác định vị trí ngắt từ bằng cách chèn các kí tự đặc biệt. Khi từ bị tràn, trình duyệt sẽ kiểm tra và sử dụng các điểm ngắt đã được chỉ định. Ngược lại, nếu không có chỉ định nào, từ sẽ không bị tách dù có tràn ra ngoài vùng hiển thị. Có hai loại kí tự dấu nối có thể sử dụng:
- Dấu nối mềm (soft hyphen, ký hiệu là
­
): Chỉ hiển thị dấu nối khi từ được ngắt xuống dòng - Dấu nối cứng (hard hyphen, ký hiệu là -): Luôn hiển thị dấu nối, bất kể có xảy ra ngắt dòng hay không
Ví dụ minh họa giúp làm rõ cách hoạt động của hyphens: manual
thông qua 3 trường hợp: không sử dụng dấu nối, sử dụng dấu nối mềm và sử dụng dấu nối cứng.
hyphens
Lưu ý khi dùng Không nên kết hợp hyphens
với word-break: break-all
, vì giá trị break-all
sẽ ghi đè cơ chế ngắt từ của hyphens
, khiến thuộc tính này không còn hiệu lực.
Ngoài ra, theo kinh nghiệm cá nhân của mình, khi sử dụng hyphens: auto
, nên kết hợp với overflow-wrap: break-word
(tránh sử dụng word-break
vì lí do nêu trên) để đảm bảo khả năng ngắt dòng vẫn được duy trì trong trường hợp auto không tự động xử lý. Điều này là do hyphens
tuân theo quy tắc ngôn ngữ: trong một số trường hợp, chẳng hạn như danh từ riêng trong tiếng Anh, dù từ bị tràn thì trình duyệt vẫn có thể không thực hiện ngắt dòng.
Bảng tổng hợp
Ba thuộc tính overflow-wrap
, word-break
và hyphens
đóng vai trò quan trọng trong việc kiểm soát cách văn bản được ngắt dòng trên trình duyệt. Việc lựa chọn thuộc tính phù hợp cần dựa trên trường hợp sử dụng cụ thể cũng như mục tiêu hiển thị.
Bảng dưới đây sẽ tổng hợp các tình huống nên dùng và các lưu ý quan trọng cho từng thuộc tính, nhằm giúp các lập trình viên có thể đưa ra những lựa chọn chính xác hơn.
Thuộc tính | overflow-wrap | word-break | hyphens |
---|---|---|---|
Trường hợp nên dùng | Phù hợp với các đoạn văn bản dài như bài blog, truyện chữ cần người dùng đọc liên tục | Phù hợp với các chỗ cần tiết kiệm không gian và không có khoảng trống lớn giữa các từ hoặc component với nhau | Phù hợp khi cần cơ chế ngắt dòng cho nhiều ngôn ngữ khác nhau |
Lợi ích chính | Người dùng dễ theo dõi nội dung hơn | Giữ bố cục hài hòa, không tạo các khoảng trống thừa | Hỗ trợ ngắt dòng thông minh với nhiều bộ quy tắc cho từng ngôn ngữ khác nhau |
Lưu ý | Cần thử nghiệm, kiểm thử khi sử dụng anywhere hoặc break-word chung với các thuộc tính có liên quan đến kích thước nội tại tối thiểu như flex hay width: min-content để tránh xảy ra các hành vi ngoài ý muốn | break-all chỉ ảnh hưởng đến các ngôn ngữ không thuộc nhóm CJK. Ngược lại, keep-all chỉ tác động lên các nhóm thuộc CJK | Cần phải xác định ngôn ngữ thông qua thuộc tính lang |
Không nên sử dụng chung với thuộc tính word-break vì sẽ bị ghi đè | |||
Với auto thì nên dùng chung với overflow-wrap để tránh một số trường hợp từ bị tràn nhưng không được ngắt bởi auto |