[{"data":1,"prerenderedAt":996},["ShallowReactive",2],{"guide-text-transformations-user-interfaces":3},{"id":4,"title":5,"body":6,"date":988,"description":989,"extension":990,"meta":991,"navigation":154,"path":992,"readingTime":181,"seo":993,"stem":994,"__hash__":995},"guides\u002Fguides\u002Ftext-transformations-user-interfaces.md","Text Transformations in User Interfaces: Patterns and Best Practices",{"type":7,"value":8,"toc":977},"minimark",[9,13,18,96,99,103,106,319,322,326,329,358,591,595,598,624,627,694,697,701,704,804,807,827,831,834,854,909,912,916,936,940,961,965,973],[10,11,12],"p",{},"Text transformations appear everywhere in user interfaces — reversed strings for visual effects, truncated labels for responsive layouts, formatted phone numbers for input fields, and case conversion for data normalization. Each transformation has practical use cases and implementation pitfalls worth understanding.",[14,15,17],"h2",{"id":16},"common-ui-text-transformations","Common UI Text Transformations",[19,20,21,37],"table",{},[22,23,24],"thead",{},[25,26,27,31,34],"tr",{},[28,29,30],"th",{},"Transformation",[28,32,33],{},"Use Case",[28,35,36],{},"Example",[38,39,40,52,63,74,85],"tbody",{},[25,41,42,46,49],{},[43,44,45],"td",{},"Reversal",[43,47,48],{},"Visual effects, palindrome games",[43,50,51],{},"\"hello\" → \"olleh\"",[25,53,54,57,60],{},[43,55,56],{},"Truncation",[43,58,59],{},"Responsive labels, cards",[43,61,62],{},"\"Very long title...\"",[25,64,65,68,71],{},[43,66,67],{},"Case conversion",[43,69,70],{},"Data normalization, headings",[43,72,73],{},"\"john doe\" → \"John Doe\"",[25,75,76,79,82],{},[43,77,78],{},"Masking",[43,80,81],{},"Passwords, credit cards",[43,83,84],{},"\"4111 **** **** 1111\"",[25,86,87,90,93],{},[43,88,89],{},"Formatting",[43,91,92],{},"Phone numbers, dates",[43,94,95],{},"\"5551234567\" → \"(555) 123-4567\"",[10,97,98],{},"Each serves a distinct purpose. Applying the wrong transformation — or applying it at the wrong layer — creates bugs and confusion.",[14,100,102],{"id":101},"css-text-transformations","CSS Text Transformations",[10,104,105],{},"Some transformations belong purely in CSS. Use CSS when the visual change is presentational and the underlying data should remain intact:",[107,108,113],"pre",{"className":109,"code":110,"language":111,"meta":112,"style":112},"language-css shiki shiki-themes github-light github-dark","\u002F* Uppercase headings — data stays lowercase *\u002F\n.heading { text-transform: uppercase; }\n\n\u002F* Capitalize names — only affects first letters *\u002F\n.name { text-transform: capitalize; }\n\n\u002F* Truncation with ellipsis *\u002F\n.truncate {\n  overflow: hidden;\n  text-transform: ellipsis;\n  white-space: nowrap;\n}\n\n\u002F* Multi-line clamping *\u002F\n.line-clamp-3 {\n  display: -webkit-box;\n  -webkit-line-clamp: 3;\n  -webkit-box-orient: vertical;\n  overflow: hidden;\n}\n","css","",[114,115,116,125,149,156,162,179,184,190,199,213,226,239,245,250,256,264,277,290,303,314],"code",{"__ignoreMap":112},[117,118,121],"span",{"class":119,"line":120},"line",1,[117,122,124],{"class":123},"sJ8bj","\u002F* Uppercase headings — data stays lowercase *\u002F\n",[117,126,128,132,136,140,143,146],{"class":119,"line":127},2,[117,129,131],{"class":130},"sScJk",".heading",[117,133,135],{"class":134},"sVt8B"," { ",[117,137,139],{"class":138},"sj4cs","text-transform",[117,141,142],{"class":134},": ",[117,144,145],{"class":138},"uppercase",[117,147,148],{"class":134},"; }\n",[117,150,152],{"class":119,"line":151},3,[117,153,155],{"emptyLinePlaceholder":154},true,"\n",[117,157,159],{"class":119,"line":158},4,[117,160,161],{"class":123},"\u002F* Capitalize names — only affects first letters *\u002F\n",[117,163,165,168,170,172,174,177],{"class":119,"line":164},5,[117,166,167],{"class":130},".name",[117,169,135],{"class":134},[117,171,139],{"class":138},[117,173,142],{"class":134},[117,175,176],{"class":138},"capitalize",[117,178,148],{"class":134},[117,180,182],{"class":119,"line":181},6,[117,183,155],{"emptyLinePlaceholder":154},[117,185,187],{"class":119,"line":186},7,[117,188,189],{"class":123},"\u002F* Truncation with ellipsis *\u002F\n",[117,191,193,196],{"class":119,"line":192},8,[117,194,195],{"class":130},".truncate",[117,197,198],{"class":134}," {\n",[117,200,202,205,207,210],{"class":119,"line":201},9,[117,203,204],{"class":138},"  overflow",[117,206,142],{"class":134},[117,208,209],{"class":138},"hidden",[117,211,212],{"class":134},";\n",[117,214,216,219,221,224],{"class":119,"line":215},10,[117,217,218],{"class":138},"  text-transform",[117,220,142],{"class":134},[117,222,223],{"class":138},"ellipsis",[117,225,212],{"class":134},[117,227,229,232,234,237],{"class":119,"line":228},11,[117,230,231],{"class":138},"  white-space",[117,233,142],{"class":134},[117,235,236],{"class":138},"nowrap",[117,238,212],{"class":134},[117,240,242],{"class":119,"line":241},12,[117,243,244],{"class":134},"}\n",[117,246,248],{"class":119,"line":247},13,[117,249,155],{"emptyLinePlaceholder":154},[117,251,253],{"class":119,"line":252},14,[117,254,255],{"class":123},"\u002F* Multi-line clamping *\u002F\n",[117,257,259,262],{"class":119,"line":258},15,[117,260,261],{"class":130},".line-clamp-3",[117,263,198],{"class":134},[117,265,267,270,272,275],{"class":119,"line":266},16,[117,268,269],{"class":138},"  display",[117,271,142],{"class":134},[117,273,274],{"class":138},"-webkit-box",[117,276,212],{"class":134},[117,278,280,283,285,288],{"class":119,"line":279},17,[117,281,282],{"class":138},"  -webkit-line-clamp",[117,284,142],{"class":134},[117,286,287],{"class":138},"3",[117,289,212],{"class":134},[117,291,293,296,298,301],{"class":119,"line":292},18,[117,294,295],{"class":138},"  -webkit-box-orient",[117,297,142],{"class":134},[117,299,300],{"class":138},"vertical",[117,302,212],{"class":134},[117,304,306,308,310,312],{"class":119,"line":305},19,[117,307,204],{"class":138},[117,309,142],{"class":134},[117,311,209],{"class":138},[117,313,212],{"class":134},[117,315,317],{"class":119,"line":316},20,[117,318,244],{"class":134},[10,320,321],{},"CSS transformations preserve the original text for copy-paste, screen readers, and search indexing. A screen reader announces \"hello\" even if CSS renders it as \"HELLO\". This separation is important for accessibility.",[14,323,325],{"id":324},"javascript-text-transformations","JavaScript Text Transformations",[10,327,328],{},"Use JavaScript when the transformation affects data semantics, not just presentation:",[330,331,332,340,346,352],"ul",{},[333,334,335,339],"li",{},[336,337,338],"strong",{},"Reversing text"," — CSS cannot reverse character order",[333,341,342,345],{},[336,343,344],{},"Masking sensitive data"," — the masked version is what should be stored or transmitted",[333,347,348,351],{},[336,349,350],{},"Formatting input"," — auto-formatting a phone number as the user types requires JS logic",[333,353,354,357],{},[336,355,356],{},"Normalizing data"," — converting user input to a consistent format before validation",[107,359,363],{"className":360,"code":361,"language":362,"meta":112,"style":112},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F Real-time phone number formatting\nfunction formatPhone(value) {\n  const digits = value.replace(\u002F\\D\u002Fg, '').slice(0, 10)\n  if (digits.length \u003C= 3) return digits\n  if (digits.length \u003C= 6) return `(${digits.slice(0, 3)}) ${digits.slice(3)}`\n  return `(${digits.slice(0, 3)}) ${digits.slice(3, 6)}-${digits.slice(6)}`\n}\n","javascript",[114,364,365,370,389,445,471,528,587],{"__ignoreMap":112},[117,366,367],{"class":119,"line":120},[117,368,369],{"class":123},"\u002F\u002F Real-time phone number formatting\n",[117,371,372,376,379,382,386],{"class":119,"line":127},[117,373,375],{"class":374},"szBVR","function",[117,377,378],{"class":130}," formatPhone",[117,380,381],{"class":134},"(",[117,383,385],{"class":384},"s4XuR","value",[117,387,388],{"class":134},") {\n",[117,390,391,394,397,400,403,406,408,412,415,417,420,423,426,429,432,434,437,439,442],{"class":119,"line":151},[117,392,393],{"class":374},"  const",[117,395,396],{"class":138}," digits",[117,398,399],{"class":374}," =",[117,401,402],{"class":134}," value.",[117,404,405],{"class":130},"replace",[117,407,381],{"class":134},[117,409,411],{"class":410},"sZZnC","\u002F",[117,413,414],{"class":138},"\\D",[117,416,411],{"class":410},[117,418,419],{"class":374},"g",[117,421,422],{"class":134},", ",[117,424,425],{"class":410},"''",[117,427,428],{"class":134},").",[117,430,431],{"class":130},"slice",[117,433,381],{"class":134},[117,435,436],{"class":138},"0",[117,438,422],{"class":134},[117,440,441],{"class":138},"10",[117,443,444],{"class":134},")\n",[117,446,447,450,453,456,459,462,465,468],{"class":119,"line":158},[117,448,449],{"class":374},"  if",[117,451,452],{"class":134}," (digits.",[117,454,455],{"class":138},"length",[117,457,458],{"class":374}," \u003C=",[117,460,461],{"class":138}," 3",[117,463,464],{"class":134},") ",[117,466,467],{"class":374},"return",[117,469,470],{"class":134}," digits\n",[117,472,473,475,477,479,481,484,486,488,491,494,497,499,501,503,505,507,510,513,515,517,519,521,523,525],{"class":119,"line":164},[117,474,449],{"class":374},[117,476,452],{"class":134},[117,478,455],{"class":138},[117,480,458],{"class":374},[117,482,483],{"class":138}," 6",[117,485,464],{"class":134},[117,487,467],{"class":374},[117,489,490],{"class":410}," `(${",[117,492,493],{"class":134},"digits",[117,495,496],{"class":410},".",[117,498,431],{"class":130},[117,500,381],{"class":410},[117,502,436],{"class":138},[117,504,422],{"class":410},[117,506,287],{"class":138},[117,508,509],{"class":410},")",[117,511,512],{"class":410},"}) ${",[117,514,493],{"class":134},[117,516,496],{"class":410},[117,518,431],{"class":130},[117,520,381],{"class":410},[117,522,287],{"class":138},[117,524,509],{"class":410},[117,526,527],{"class":410},"}`\n",[117,529,530,533,535,537,539,541,543,545,547,549,551,553,555,557,559,561,563,565,568,570,573,575,577,579,581,583,585],{"class":119,"line":181},[117,531,532],{"class":374},"  return",[117,534,490],{"class":410},[117,536,493],{"class":134},[117,538,496],{"class":410},[117,540,431],{"class":130},[117,542,381],{"class":410},[117,544,436],{"class":138},[117,546,422],{"class":410},[117,548,287],{"class":138},[117,550,509],{"class":410},[117,552,512],{"class":410},[117,554,493],{"class":134},[117,556,496],{"class":410},[117,558,431],{"class":130},[117,560,381],{"class":410},[117,562,287],{"class":138},[117,564,422],{"class":410},[117,566,567],{"class":138},"6",[117,569,509],{"class":410},[117,571,572],{"class":410},"}-${",[117,574,493],{"class":134},[117,576,496],{"class":410},[117,578,431],{"class":130},[117,580,381],{"class":410},[117,582,567],{"class":138},[117,584,509],{"class":410},[117,586,527],{"class":410},[117,588,589],{"class":119,"line":186},[117,590,244],{"class":134},[14,592,594],{"id":593},"reversed-text-in-ui-design","Reversed Text in UI Design",[10,596,597],{},"Text reversal has legitimate UI applications beyond novelty:",[330,599,600,606,612,618],{},[333,601,602,605],{},[336,603,604],{},"RTL language support"," — Arabic and Hebrew interfaces need bidirectional text handling",[333,607,608,611],{},[336,609,610],{},"Visual effects"," — mirror text for logos, artistic headers, or game interfaces",[333,613,614,617],{},[336,615,616],{},"Data verification"," — displaying reversed strings alongside original for comparison (checksums, serial numbers)",[333,619,620,623],{},[336,621,622],{},"Accessibility aid"," — some dyslexia tools present text in alternative orientations",[10,625,626],{},"When implementing reversed text, consider:",[107,628,632],{"className":629,"code":630,"language":631,"meta":112,"style":112},"language-html shiki shiki-themes github-light github-dark","\u003C!-- Visual reversal via CSS — preserves text for screen readers -->\n\u003Cspan aria-label=\"hello\" style=\"direction: rtl; unicode-bidi: bidi-override;\">hello\u003C\u002Fspan>\n\n\u003C!-- Semantic reversal via JS — changes the actual text content -->\n\u003Cspan>{{ reversedText }}\u003C\u002Fspan>\n","html",[114,633,634,639,672,676,681],{"__ignoreMap":112},[117,635,636],{"class":119,"line":120},[117,637,638],{"class":123},"\u003C!-- Visual reversal via CSS — preserves text for screen readers -->\n",[117,640,641,644,647,650,653,656,659,661,664,667,669],{"class":119,"line":127},[117,642,643],{"class":134},"\u003C",[117,645,117],{"class":646},"s9eBZ",[117,648,649],{"class":130}," aria-label",[117,651,652],{"class":134},"=",[117,654,655],{"class":410},"\"hello\"",[117,657,658],{"class":130}," style",[117,660,652],{"class":134},[117,662,663],{"class":410},"\"direction: rtl; unicode-bidi: bidi-override;\"",[117,665,666],{"class":134},">hello\u003C\u002F",[117,668,117],{"class":646},[117,670,671],{"class":134},">\n",[117,673,674],{"class":119,"line":151},[117,675,155],{"emptyLinePlaceholder":154},[117,677,678],{"class":119,"line":158},[117,679,680],{"class":123},"\u003C!-- Semantic reversal via JS — changes the actual text content -->\n",[117,682,683,685,687,690,692],{"class":119,"line":164},[117,684,643],{"class":134},[117,686,117],{"class":646},[117,688,689],{"class":134},">{{ reversedText }}\u003C\u002F",[117,691,117],{"class":646},[117,693,671],{"class":134},[10,695,696],{},"The CSS approach keeps \"hello\" accessible while displaying \"olleh\". The JS approach changes the actual content. Choose based on whether the reversal is visual decoration or semantic content.",[14,698,700],{"id":699},"input-masking-patterns","Input Masking Patterns",[10,702,703],{},"Masking transforms sensitive input into unreadable characters while preserving the original value in memory:",[107,705,707],{"className":360,"code":706,"language":362,"meta":112,"style":112},"\u002F\u002F Credit card masking — show only last 4 digits\nfunction maskCard(cardNumber) {\n  const last4 = cardNumber.slice(-4)\n  const masked = '*'.repeat(cardNumber.length - 4)\n  return masked + last4\n}\n\u002F\u002F \"4111111111111111\" → \"************1111\"\n",[114,708,709,714,728,752,782,795,799],{"__ignoreMap":112},[117,710,711],{"class":119,"line":120},[117,712,713],{"class":123},"\u002F\u002F Credit card masking — show only last 4 digits\n",[117,715,716,718,721,723,726],{"class":119,"line":127},[117,717,375],{"class":374},[117,719,720],{"class":130}," maskCard",[117,722,381],{"class":134},[117,724,725],{"class":384},"cardNumber",[117,727,388],{"class":134},[117,729,730,732,735,737,740,742,744,747,750],{"class":119,"line":151},[117,731,393],{"class":374},[117,733,734],{"class":138}," last4",[117,736,399],{"class":374},[117,738,739],{"class":134}," cardNumber.",[117,741,431],{"class":130},[117,743,381],{"class":134},[117,745,746],{"class":374},"-",[117,748,749],{"class":138},"4",[117,751,444],{"class":134},[117,753,754,756,759,761,764,766,769,772,774,777,780],{"class":119,"line":158},[117,755,393],{"class":374},[117,757,758],{"class":138}," masked",[117,760,399],{"class":374},[117,762,763],{"class":410}," '*'",[117,765,496],{"class":134},[117,767,768],{"class":130},"repeat",[117,770,771],{"class":134},"(cardNumber.",[117,773,455],{"class":138},[117,775,776],{"class":374}," -",[117,778,779],{"class":138}," 4",[117,781,444],{"class":134},[117,783,784,786,789,792],{"class":119,"line":164},[117,785,532],{"class":374},[117,787,788],{"class":134}," masked ",[117,790,791],{"class":374},"+",[117,793,794],{"class":134}," last4\n",[117,796,797],{"class":119,"line":181},[117,798,244],{"class":134},[117,800,801],{"class":119,"line":186},[117,802,803],{"class":123},"\u002F\u002F \"4111111111111111\" → \"************1111\"\n",[10,805,806],{},"Common mistakes:",[330,808,809,815,821],{},[333,810,811,814],{},[336,812,813],{},"Masking too early"," — if you mask before validation, error messages reference the masked value instead of the original",[333,816,817,820],{},[336,818,819],{},"Not masking at all"," — logging unmasked credit card numbers violates PCI-DSS",[333,822,823,826],{},[336,824,825],{},"Masking in the wrong layer"," — mask for display output, not for internal state or API payloads",[14,828,830],{"id":829},"performance-considerations","Performance Considerations",[10,832,833],{},"Text transformations in lists and tables can create performance issues at scale:",[330,835,836,842,848],{},[333,837,838,841],{},[336,839,840],{},"Avoid transforming in render loops"," — cache transformed values or compute them in a composable\u002Fstore",[333,843,844,847],{},[336,845,846],{},"Use virtual scrolling for large lists"," — transforming 10,000 items on mount blocks the main thread",[333,849,850,853],{},[336,851,852],{},"Debounce input formatting"," — formatting on every keystroke causes jank on slow devices",[107,855,857],{"className":360,"code":856,"language":362,"meta":112,"style":112},"\u002F\u002F Debounced formatter for search input\nconst formattedSearch = computed(() => {\n  return searchQuery.value.trim().toLowerCase()\n})\n",[114,858,859,864,885,904],{"__ignoreMap":112},[117,860,861],{"class":119,"line":120},[117,862,863],{"class":123},"\u002F\u002F Debounced formatter for search input\n",[117,865,866,869,872,874,877,880,883],{"class":119,"line":127},[117,867,868],{"class":374},"const",[117,870,871],{"class":138}," formattedSearch",[117,873,399],{"class":374},[117,875,876],{"class":130}," computed",[117,878,879],{"class":134},"(() ",[117,881,882],{"class":374},"=>",[117,884,198],{"class":134},[117,886,887,889,892,895,898,901],{"class":119,"line":151},[117,888,532],{"class":374},[117,890,891],{"class":134}," searchQuery.value.",[117,893,894],{"class":130},"trim",[117,896,897],{"class":134},"().",[117,899,900],{"class":130},"toLowerCase",[117,902,903],{"class":134},"()\n",[117,905,906],{"class":119,"line":158},[117,907,908],{"class":134},"})\n",[10,910,911],{},"Computed properties in Vue handle this naturally — they cache results and only recompute when dependencies change.",[14,913,915],{"id":914},"key-takeaways","Key Takeaways",[330,917,918,921,927,930,933],{},[333,919,920],{},"Use CSS for presentational transformations (uppercase, ellipsis); use JS for semantic transformations (reversal, masking, formatting)",[333,922,923,924,926],{},"CSS ",[114,925,139],{}," preserves original text for screen readers and copy-paste — always prefer it for case changes",[333,928,929],{},"Reversed text in UI has real applications: RTL support, visual branding, data verification",[333,931,932],{},"Mask sensitive data at the display layer, not the internal state layer",[333,934,935],{},"Cache transformation results for large lists and debounce frequent input formatting",[14,937,939],{"id":938},"related-guides","Related Guides",[330,941,942,949,955],{},[333,943,944],{},[945,946,948],"a",{"href":947},"\u002Fguides\u002Ftext-reversal-techniques","Text Reversal Techniques: Methods and Applications",[333,950,951],{},[945,952,954],{"href":953},"\u002Fguides\u002Fmirror-text-guide","Mirror Text Guide: How Reversed Text Works",[333,956,957],{},[945,958,960],{"href":959},"\u002Fguides\u002Fpalindrome-detection-algorithms","Palindrome Detection Algorithms",[14,962,964],{"id":963},"try-it-yourself","Try It Yourself",[10,966,967,968,972],{},"Reverse, mask, and transform text instantly with our free ",[945,969,971],{"href":970},"\u002Ftools\u002Ftext-reverser","Text Reverser"," tool. Paste any text, see the reversed output, and experiment with text transformation patterns for your own projects.",[974,975,976],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":112,"searchDepth":127,"depth":127,"links":978},[979,980,981,982,983,984,985,986,987],{"id":16,"depth":127,"text":17},{"id":101,"depth":127,"text":102},{"id":324,"depth":127,"text":325},{"id":593,"depth":127,"text":594},{"id":699,"depth":127,"text":700},{"id":829,"depth":127,"text":830},{"id":914,"depth":127,"text":915},{"id":938,"depth":127,"text":939},{"id":963,"depth":127,"text":964},"2026-05-28","Explore common text transformation patterns in UI design — reversing, truncating, formatting, and transforming text with accessible, performant implementations.","md",{"immutable":154},"\u002Fguides\u002Ftext-transformations-user-interfaces",{"title":5,"description":989},"guides\u002Ftext-transformations-user-interfaces","dFVD91S9HfL3wdOs8omrAg1aV386P7E8tJU8D67i7L8",1780401337518]