[{"data":1,"prerenderedAt":1314},["ShallowReactive",2],{"blog-trail-design-accessibility":3,"blog-post-design-accessibility-semantic-html-beyond-divs":6},{"themeName":4,"topicTitle":5},"Design","Accessibility",{"doc":7,"tocLinks":1292},{"id":8,"title":9,"author":10,"body":11,"category":5,"code":1278,"color":1278,"count":1278,"description":1279,"extension":1280,"meta":1281,"name":1278,"navigation":1282,"path":1283,"postCount":1278,"publishedAt":1284,"readTime":1285,"seo":1286,"slug":1287,"stem":1288,"themeId":1278,"themeslug":1278,"topicId":1289,"type":1290,"__hash__":1291},"blog\u002Fblog\u002Fposts\u002Faccessibility\u002Fsemantic-html-beyond-divs.md","Semantic HTML Beyond \"div Soup\"","Hardeep Kumar",{"type":12,"value":13,"toc":1254},"minimark",[14,18,36,39,42,59,76,79,213,220,223,226,231,234,241,246,249,260,280,286,300,304,307,310,313,328,331,334,365,368,371,374,389,395,398,407,410,461,464,470,476,480,483,488,491,538,541,566,569,572,576,579,604,610,613,617,620,635,638,641,645,651,654,664,667,671,674,677,706,713,727,731,740,757,760,763,767,787,794,797,801,816,819,825,829,836,847,874,881,885,904,907,913,921,925,928,949,952,963,966,970,981,991,995,1001,1004,1021,1027,1030,1033,1037,1046,1049,1057,1060,1092,1095,1116,1119,1123,1126,1129,1135,1138,1142,1145,1168,1171,1175,1178,1192,1203,1207,1210,1213,1216,1219,1228,1231,1234,1247,1250],[15,16,17],"p",{},"There’s a phase most developers go through when working with HTML.",[15,19,20,21,25,26,25,29,25,32,35],{},"At first, everything is confusing. There are too many tags — ",[22,23,24],"code",{},"\u003Carticle>",", ",[22,27,28],{},"\u003Csection>",[22,30,31],{},"\u003Cnav>",[22,33,34],{},"\u003Caside>"," — and you’re not entirely sure when to use what. So you do what any practical person would do:",[15,37,38],{},"You ignore all of them.",[15,40,41],{},"Instead, you reach for the one tag that seems to solve everything:",[43,44,49],"pre",{"className":45,"code":46,"language":47,"meta":48,"style":48},"language-html shiki shiki-themes nord","\u003Cdiv>\n","html","",[22,50,51],{"__ignoreMap":48},[52,53,56],"span",{"class":54,"line":55},"line",1,[52,57,46],{"class":58},"sGPm4",[15,60,61,62,65,66,68,69,71,72,75],{},"Need a container? ",[22,63,64],{},"\u003Cdiv>",". Need a layout? ",[22,67,64],{},". Need a button? …okay, maybe still ",[22,70,64],{}," with an ",[22,73,74],{},"onClick",".",[15,77,78],{},"Before long, your entire page looks like this:",[43,80,82],{"className":45,"code":81,"language":47,"meta":48,"style":48},"\u003Cdiv class=\"container\">\n  \u003Cdiv class=\"header\">\n    \u003Cdiv class=\"nav\">\n      \u003Cdiv class=\"nav-item\">Home\u003C\u002Fdiv>\n      \u003Cdiv class=\"nav-item\">About\u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n",[22,83,84,109,128,147,174,196,202,208],{"__ignoreMap":48},[52,85,86,89,93,97,100,104,106],{"class":54,"line":55},[52,87,88],{"class":58},"\u003Cdiv",[52,90,92],{"class":91},"sX7Mg"," class",[52,94,96],{"class":95},"sNYnk","=",[52,98,99],{"class":95},"\"",[52,101,103],{"class":102},"sUFv7","container",[52,105,99],{"class":95},[52,107,108],{"class":58},">\n",[52,110,112,115,117,119,121,124,126],{"class":54,"line":111},2,[52,113,114],{"class":58},"  \u003Cdiv",[52,116,92],{"class":91},[52,118,96],{"class":95},[52,120,99],{"class":95},[52,122,123],{"class":102},"header",[52,125,99],{"class":95},[52,127,108],{"class":58},[52,129,131,134,136,138,140,143,145],{"class":54,"line":130},3,[52,132,133],{"class":58},"    \u003Cdiv",[52,135,92],{"class":91},[52,137,96],{"class":95},[52,139,99],{"class":95},[52,141,142],{"class":102},"nav",[52,144,99],{"class":95},[52,146,108],{"class":58},[52,148,150,153,155,157,159,162,164,167,171],{"class":54,"line":149},4,[52,151,152],{"class":58},"      \u003Cdiv",[52,154,92],{"class":91},[52,156,96],{"class":95},[52,158,99],{"class":95},[52,160,161],{"class":102},"nav-item",[52,163,99],{"class":95},[52,165,166],{"class":58},">",[52,168,170],{"class":169},"s0_w5","Home",[52,172,173],{"class":58},"\u003C\u002Fdiv>\n",[52,175,177,179,181,183,185,187,189,191,194],{"class":54,"line":176},5,[52,178,152],{"class":58},[52,180,92],{"class":91},[52,182,96],{"class":95},[52,184,99],{"class":95},[52,186,161],{"class":102},[52,188,99],{"class":95},[52,190,166],{"class":58},[52,192,193],{"class":169},"About",[52,195,173],{"class":58},[52,197,199],{"class":54,"line":198},6,[52,200,201],{"class":58},"    \u003C\u002Fdiv>\n",[52,203,205],{"class":54,"line":204},7,[52,206,207],{"class":58},"  \u003C\u002Fdiv>\n",[52,209,211],{"class":54,"line":210},8,[52,212,173],{"class":58},[15,214,215,216,75],{},"Congratulations. You’ve built what’s commonly known as ",[217,218,219],"strong",{},"div soup",[15,221,222],{},"It works. It renders. Nobody complains — at least not immediately.",[15,224,225],{},"But under the surface, you’ve quietly thrown away one of the most powerful features of HTML:",[15,227,228],{},[217,229,230],{},"Meaning.",[15,232,233],{},"Browsers, assistive tech, search engines, and future-you all consume structure — not your Figma frame. When structure is missing, you don’t get a polite error. You get confusion, skipped content, wrong tab order, and users who quietly leave.",[15,235,236,237,240],{},"Semantic HTML isn’t nostalgia. It’s ",[217,238,239],{},"the contract"," between what you built and everything that isn’t a visual screenshot.",[242,243,245],"h2",{"id":244},"html-was-never-just-about-layout","HTML Was Never Just About Layout",[15,247,248],{},"Somewhere along the way, HTML got reduced to “that thing we use to structure the page before CSS makes it look good.”",[15,250,251,252,259],{},"But HTML was never meant to be just visual scaffolding. It’s a language designed to describe ",[217,253,254,255],{},"what something ",[256,257,258],"em",{},"is",", not just how it looks.",[261,262,263,269,274],"ul",{},[264,265,266,268],"li",{},[22,267,31],{}," isn’t just a container — it’s navigation.",[264,270,271,273],{},[22,272,24],{}," isn’t just a box — it’s a standalone piece of content.",[264,275,276,279],{},[22,277,278],{},"\u003Cbutton>"," isn’t just clickable — it’s an interactive control.",[15,281,282,283,285],{},"When you replace everything with ",[22,284,64],{},", you strip away that meaning.",[15,287,288,291,292,295,296,299],{},[217,289,290],{},"What “semantic” means in practice:"," choose elements that describe ",[217,293,294],{},"purpose",", not just layout. You’re not doing this for pedantry. You’re doing it so ",[217,297,298],{},"software can build a model"," of your page without guessing.",[242,301,303],{"id":302},"accessibility-the-part-most-people-ignore","Accessibility: The Part Most People Ignore",[15,305,306],{},"Let’s talk about the elephant in the room: accessibility.",[15,308,309],{},"When you use proper semantic elements, assistive technologies don’t have to guess what your UI is doing. They already know.",[15,311,312],{},"A screen reader encountering this:",[43,314,316],{"className":45,"code":315,"language":47,"meta":48,"style":48},"\u003Cbutton>Submit\u003C\u002Fbutton>\n",[22,317,318],{"__ignoreMap":48},[52,319,320,322,325],{"class":54,"line":55},[52,321,278],{"class":58},[52,323,324],{"class":169},"Submit",[52,326,327],{"class":58},"\u003C\u002Fbutton>\n",[15,329,330],{},"…knows it’s a button. It announces it properly. It supports keyboard interaction automatically.",[15,332,333],{},"Now compare that to:",[43,335,337],{"className":45,"code":336,"language":47,"meta":48,"style":48},"\u003Cdiv onclick=\"submitForm()\">Submit\u003C\u002Fdiv>\n",[22,338,339],{"__ignoreMap":48},[52,340,341,343,346,348,350,354,357,359,361,363],{"class":54,"line":55},[52,342,88],{"class":58},[52,344,345],{"class":91}," onclick",[52,347,96],{"class":95},[52,349,99],{"class":95},[52,351,353],{"class":352},"st_Lx","submitForm",[52,355,356],{"class":102},"()",[52,358,99],{"class":95},[52,360,166],{"class":58},[52,362,324],{"class":169},[52,364,173],{"class":58},[15,366,367],{},"To a screen reader, that’s just… a box.",[15,369,370],{},"No role. No behavior. No accessibility.",[15,372,373],{},"So now you have to manually add:",[261,375,376,381,386],{},[264,377,378],{},[22,379,380],{},"role=\"button\"",[264,382,383],{},[22,384,385],{},"tabindex=\"0\"",[264,387,388],{},"Keyboard event handlers",[15,390,391,392,394],{},"In other words, you’re rebuilding what ",[22,393,278],{}," already gives you for free.",[15,396,397],{},"This is the irony of div soup:",[399,400,401],"blockquote",{},[15,402,403,404,406],{},"The more you rely on ",[22,405,64],{},", the more work you create for yourself.",[15,408,409],{},"Somewhere along the line, people learned they can write:",[43,411,413],{"className":45,"code":412,"language":47,"meta":48,"style":48},"\u003Cdiv role=\"button\" tabindex=\"0\" onclick=\"...\">Save\u003C\u002Fdiv>\n",[22,414,415],{"__ignoreMap":48},[52,416,417,419,422,424,426,429,431,434,436,438,441,443,445,447,449,452,454,456,459],{"class":54,"line":55},[52,418,88],{"class":58},[52,420,421],{"class":91}," role",[52,423,96],{"class":95},[52,425,99],{"class":95},[52,427,428],{"class":102},"button",[52,430,99],{"class":95},[52,432,433],{"class":91}," tabindex",[52,435,96],{"class":95},[52,437,99],{"class":95},[52,439,440],{"class":102},"0",[52,442,99],{"class":95},[52,444,345],{"class":91},[52,446,96],{"class":95},[52,448,99],{"class":95},[52,450,451],{"class":58},"...",[52,453,99],{"class":95},[52,455,166],{"class":58},[52,457,458],{"class":169},"Save",[52,460,173],{"class":58},[15,462,463],{},"And yes — with enough attributes and keyboard handlers — you can approximate a button.",[15,465,466,467,469],{},"You’ve also signed up to re-implement focus behavior, activation (Enter \u002F Space), disabled state, name computation for assistive tech, and consistency with every real ",[22,468,278],{}," on the OS.",[15,471,472,475],{},[217,473,474],{},"Rule of thumb:"," if a native element exists, use it first. ARIA patches gaps; it doesn’t replace semantics.",[242,477,479],{"id":478},"semantics-improve-more-than-accessibility","Semantics Improve More Than Accessibility",[15,481,482],{},"Accessibility is the strongest argument, but it’s not the only one.",[484,485,487],"h3",{"id":486},"your-code-becomes-easier-to-read","Your code becomes easier to read",[15,489,490],{},"Compare these two:",[43,492,494],{"className":45,"code":493,"language":47,"meta":48,"style":48},"\u003Cdiv class=\"top-bar\">\n  \u003Cdiv class=\"menu\">...\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n",[22,495,496,513,534],{"__ignoreMap":48},[52,497,498,500,502,504,506,509,511],{"class":54,"line":55},[52,499,88],{"class":58},[52,501,92],{"class":91},[52,503,96],{"class":95},[52,505,99],{"class":95},[52,507,508],{"class":102},"top-bar",[52,510,99],{"class":95},[52,512,108],{"class":58},[52,514,515,517,519,521,523,526,528,530,532],{"class":54,"line":111},[52,516,114],{"class":58},[52,518,92],{"class":91},[52,520,96],{"class":95},[52,522,99],{"class":95},[52,524,525],{"class":102},"menu",[52,527,99],{"class":95},[52,529,166],{"class":58},[52,531,451],{"class":169},[52,533,173],{"class":58},[52,535,536],{"class":54,"line":130},[52,537,173],{"class":58},[15,539,540],{},"vs.",[43,542,544],{"className":45,"code":543,"language":47,"meta":48,"style":48},"\u003Cheader>\n  \u003Cnav>...\u003C\u002Fnav>\n\u003C\u002Fheader>\n",[22,545,546,551,561],{"__ignoreMap":48},[52,547,548],{"class":54,"line":55},[52,549,550],{"class":58},"\u003Cheader>\n",[52,552,553,556,558],{"class":54,"line":111},[52,554,555],{"class":58},"  \u003Cnav>",[52,557,451],{"class":169},[52,559,560],{"class":58},"\u003C\u002Fnav>\n",[52,562,563],{"class":54,"line":130},[52,564,565],{"class":58},"\u003C\u002Fheader>\n",[15,567,568],{},"The second one reads like a sentence. You don’t need class names to understand the structure.",[15,570,571],{},"That matters more than you think — especially when you come back to your code after a few months and wonder what past-you was doing.",[484,573,575],{"id":574},"you-get-built-in-behavior","You get built-in behavior",[15,577,578],{},"Semantic elements come with default behavior:",[261,580,581,586,592,598],{},[264,582,583,585],{},[22,584,278],{}," → keyboard support, focus handling",[264,587,588,591],{},[22,589,590],{},"\u003Cform>"," → submission behavior",[264,593,594,597],{},[22,595,596],{},"\u003Clabel>"," → links to inputs",[264,599,600,603],{},[22,601,602],{},"\u003Ca>"," → navigation semantics",[15,605,606,607,609],{},"When you ignore these and roll your own with ",[22,608,64],{},", you’re opting out of decades of browser optimization — and signing up to reimplement it yourself.",[15,611,612],{},"That’s rarely a good trade.",[484,614,616],{"id":615},"seo-yes-it-still-matters","SEO (yes, it still matters)",[15,618,619],{},"Search engines don’t just look at your text — they look at structure.",[15,621,622,623,25,626,25,628,630,631,634],{},"Using elements like ",[22,624,625],{},"\u003Cmain>",[22,627,24],{},[22,629,28],{},", and ",[22,632,633],{},"\u003Cheader>"," helps them understand what your content is about.",[15,636,637],{},"Is it the primary content? A sidebar? Navigation? A footer?",[15,639,640],{},"You’re essentially giving them a map instead of a pile of unlabeled boxes.",[242,642,644],{"id":643},"links-that-behave-like-links","Links That Behave Like Links",[15,646,647,648,75],{},"Another favorite: ",[22,649,650],{},"\u003Cspan onClick={navigate}>Go to dashboard\u003C\u002Fspan>",[15,652,653],{},"It isn’t in the link history. It doesn’t expose a real URL to “open in new tab.” It doesn’t get discovered the way crawlers and assistive tech expect links to be discovered.",[15,655,656,657,660,661,75],{},"Use ",[22,658,659],{},"\u003Ca href=\"...\">"," for navigation. If you’re in a SPA, the router can still intercept the click — you keep ",[217,662,663],{},"semantics and behavior",[15,665,666],{},"If the UI “looks like a link” but isn’t one, you’ve built a costume.",[242,668,670],{"id":669},"forms-labels-are-part-of-the-control","Forms: Labels Are Part of the Control",[15,672,673],{},"Inputs without associated labels are a structural bug, not a copy problem.",[15,675,676],{},"The accessible name for a field comes from:",[261,678,679,690,695],{},[264,680,681,682,685,686,689],{},"A ",[22,683,684],{},"\u003Clabel for=\"id\">"," pointing at the input’s ",[22,687,688],{},"id",", or",[264,691,692,693,689],{},"The input wrapped in ",[22,694,596],{},[264,696,697,698,701,702,705],{},"In limited cases, ",[22,699,700],{},"aria-label"," \u002F ",[22,703,704],{},"aria-labelledby"," when design truly has no visible label (rare for standard forms).",[15,707,708,709,712],{},"Placeholder text is ",[217,710,711],{},"not"," a label. It disappears when people type, it’s often low contrast, and screen readers handle it inconsistently compared to a real label.",[15,714,715,716,719,720,723,724,726],{},"Groups of radio buttons or checkboxes belong in ",[22,717,718],{},"\u003Cfieldset>"," with ",[22,721,722],{},"\u003Clegend>"," — not a bold ",[22,725,64],{}," pretending to be a section title.",[242,728,730],{"id":729},"lists-when-you-mean-a-list-say-so","Lists: When You Mean a List, Say So",[15,732,733,734,736,737,75],{},"If you render ten rows of “card” markup as sibling ",[22,735,64],{},"s because CSS grid is easier that way, you might still have a list ",[217,738,739],{},"semantically",[261,741,742,751],{},[264,743,656,744,701,747,750],{},[22,745,746],{},"\u003Cul>",[22,748,749],{},"\u003Col>"," when order or grouping matters to understanding.",[264,752,656,753,756],{},[22,754,755],{},"\u003Cli>"," for items.",[15,758,759],{},"Screen readers announce list boundaries (“list, three items”). That context matters for long feeds and settings screens.",[15,761,762],{},"If everything is anonymous siblings, users hear a wall of text with no scaffolding.",[242,764,766],{"id":765},"tables-for-tabular-data","Tables for Tabular Data",[15,768,769,770,773,774,719,777,780,781,701,784,786],{},"If data is ",[217,771,772],{},"tabular"," — rows share columns with a meaningful relationship — use ",[22,775,776],{},"\u003Ctable>",[22,778,779],{},"\u003Cth scope=\"col\">"," (or explicit ",[22,782,783],{},"headers",[22,785,688],{}," wiring for complex grids).",[15,788,789,790,793],{},"CSS can make a table look like cards on mobile. ",[217,791,792],{},"Responsiveness is not an excuse"," to throw away table semantics for price comparisons, ledgers, or schedules.",[15,795,796],{},"“Div tables” were a dark chapter. We have better layout tools now.",[242,798,800],{"id":799},"images-and-media","Images and Media",[15,802,803,804,807,808,811,812,815],{},"Meaningful images need ",[217,805,806],{},"descriptive"," ",[22,809,810],{},"alt"," text. Decorative images need ",[22,813,814],{},"alt=\"\""," so assistive tech skips them.",[15,817,818],{},"Video needs captions. Audio needs transcripts if the information isn’t elsewhere.",[15,820,821,822,75],{},"None of this replaces semantic structure around the page — but it completes the picture: ",[217,823,824],{},"content type matches reality",[242,826,828],{"id":827},"headings-are-a-map-not-typography","Headings Are a Map, Not Typography",[15,830,831,832,835],{},"Design systems love type scales. That’s fine — until “this looks like an h3” becomes an actual ",[22,833,834],{},"\u003Ch3>"," in the wrong place.",[15,837,838,839,842,843,846],{},"Headings define ",[217,840,841],{},"outline",", not font size. Screen reader users often navigate by jumping from heading to heading. If your levels skip around or repeat six ",[22,844,845],{},"h1","s because styling was convenient, that map is lying.",[261,848,849,855,871],{},[264,850,851,852,854],{},"One ",[22,853,845],{}," per page (typically the page topic).",[264,856,857,858,860,861,864,865,867,868,870],{},"Don’t skip levels because it “felt cleaner” (",[22,859,845],{}," → ",[22,862,863],{},"h4"," with no ",[22,866,242],{},"\u002F",[22,869,484],{},").",[264,872,873],{},"Match visual importance to structural importance as closely as you can.",[15,875,876,877,880],{},"When design and outline disagree, ",[217,878,879],{},"fix the CSS",", not the heading levels.",[242,882,884],{"id":883},"landmarks-boring-labels-that-save-people-hours","Landmarks: Boring Labels That Save People Hours",[15,886,887,888,25,890,25,892,25,894,897,898,900,901,75],{},"Elements like ",[22,889,625],{},[22,891,31],{},[22,893,633],{},[22,895,896],{},"\u003Cfooter>",", and (when appropriate) ",[22,899,34],{}," create ",[217,902,903],{},"landmarks",[15,905,906],{},"Users can jump to “main” or “navigation” instead of tabbing through every icon button you put in the header. That’s not a niche power-user trick — it’s how a lot of people efficiently use the web.",[15,908,909,910,912],{},"If everything lives in anonymous ",[22,911,64],{},"s, the only strategy is brute force: read or tab from the top and hope.",[15,914,915,920],{},[217,916,917,918],{},"Exactly one ",[22,919,625],{}," per document (with rare documented exceptions) so “skip to main” has a destination.",[242,922,924],{"id":923},"aria-when-you-need-it-not-as-default-paint","ARIA When You Need It — Not as Default Paint",[15,926,927],{},"Valid uses of ARIA include:",[261,929,930,937,946],{},[264,931,932,933,936],{},"Live regions for async status updates (",[22,934,935],{},"aria-live",") when there’s no other polite announcement channel.",[264,938,939,940,701,943,75],{},"Expanding panels when you can’t use ",[22,941,942],{},"\u003Cdetails>",[22,944,945],{},"\u003Csummary>",[264,947,948],{},"Correcting mistakes in third-party markup you can’t replace yet.",[15,950,951],{},"Invalid uses include:",[261,953,954],{},[264,955,956,957,959,960,75],{},"Slapping ",[22,958,380],{}," on everything because the design system’s “Button” component is a ",[22,961,962],{},"div",[15,964,965],{},"Start with HTML. Measure twice before adding roles.",[242,967,969],{"id":968},"language-and-direction","Language and Direction",[15,971,972,973,976,977,980],{},"Set ",[22,974,975],{},"lang"," on ",[22,978,979],{},"\u003Chtml>"," (or relevant subtree) so pronunciation and hyphenation behave. If you ship mixed-language UI, mark the local subtree.",[15,982,983,986,987,990],{},[22,984,985],{},"dir"," for RTL isn’t optional for real bilingual products — it affects layout ",[217,988,989],{},"and"," reading order assumptions.",[242,992,994],{"id":993},"why-div-soup-happens-in-the-first-place","Why Div Soup Happens in the First Place",[15,996,997,998,1000],{},"To be fair, developers don’t use ",[22,999,64],{}," everywhere because they’re lazy.",[15,1002,1003],{},"It happens because:",[261,1005,1006,1012,1015,1018],{},[264,1007,1008,1009,1011],{},"Frameworks abstract HTML away (hello, endless ",[22,1010,64],{}," trees in React).",[264,1013,1014],{},"CSS handles layout, so semantics feel “optional.”",[264,1016,1017],{},"Nobody enforces it in most teams.",[264,1019,1020],{},"It’s faster in the moment.",[15,1022,1023,1024,75],{},"And honestly? It ",[256,1025,1026],{},"works",[15,1028,1029],{},"That’s what makes it dangerous.",[15,1031,1032],{},"Because the problems — accessibility gaps, maintainability issues — don’t show up immediately. They creep in slowly.",[242,1034,1036],{"id":1035},"a-better-way-without-becoming-a-purist","A Better Way (Without Becoming a Purist)",[15,1038,1039,1040,1042,1043,1045],{},"This isn’t about banning ",[22,1041,64],{},". ",[22,1044,64],{}," is useful. You’ll always need it.",[15,1047,1048],{},"The goal is simple:",[399,1050,1051],{},[15,1052,1053,1054,1056],{},"Use semantic elements when they exist. Use ",[22,1055,64],{}," when they don’t.",[15,1058,1059],{},"You don’t need to memorize every HTML tag. Just start with the obvious ones:",[261,1061,1062,1067,1072,1077,1082,1087],{},[264,1063,656,1064,1066],{},[22,1065,633],{}," for headers.",[264,1068,656,1069,1071],{},[22,1070,31],{}," for navigation.",[264,1073,656,1074,1076],{},[22,1075,625],{}," for main content.",[264,1078,656,1079,1081],{},[22,1080,28],{}," for logical grouping.",[264,1083,656,1084,1086],{},[22,1085,24],{}," for standalone content.",[264,1088,656,1089,1091],{},[22,1090,278],{}," for buttons (seriously, just do it).",[15,1093,1094],{},"If you catch yourself writing:",[43,1096,1098],{"className":45,"code":1097,"language":47,"meta":48,"style":48},"\u003Cdiv class=\"button\">\n",[22,1099,1100],{"__ignoreMap":48},[52,1101,1102,1104,1106,1108,1110,1112,1114],{"class":54,"line":55},[52,1103,88],{"class":58},[52,1105,92],{"class":91},[52,1107,96],{"class":95},[52,1109,99],{"class":95},[52,1111,428],{"class":102},[52,1113,99],{"class":95},[52,1115,108],{"class":58},[15,1117,1118],{},"…pause for a second. There’s probably a better option.",[242,1120,1122],{"id":1121},"the-subtle-shift","The Subtle Shift",[15,1124,1125],{},"The real change isn’t technical — it’s mental.",[15,1127,1128],{},"Instead of asking: “What do I need to style this?”",[15,1130,1131,1132,1134],{},"Start asking: “What ",[256,1133,258],{}," this element?”",[15,1136,1137],{},"That small shift leads to better decisions automatically.",[242,1139,1141],{"id":1140},"this-isnt-only-about-screen-readers","This Isn’t Only About Screen Readers",[15,1143,1144],{},"Semantic structure helps:",[261,1146,1147,1153,1159],{},[264,1148,1149,1152],{},[217,1150,1151],{},"Keyboard users"," — focusable controls are predictable when you use real links and buttons.",[264,1154,1155,1158],{},[217,1156,1157],{},"Search engines"," — content hierarchy still signals what matters.",[264,1160,1161,1164,1165,1167],{},[217,1162,1163],{},"Your team"," — the next developer reads ",[22,1166,24],{}," vs “div #3” faster than you think.",[15,1169,1170],{},"Accessibility conversations often get framed as “edge cases.” That’s a statistical mistake. Disability is common; situational limits (sunlight, one hand, slow network) are universal.",[242,1172,1174],{"id":1173},"a-practical-review-habit","A Practical Review Habit",[15,1176,1177],{},"Before merge, ask:",[261,1179,1180,1183,1186,1189],{},[264,1181,1182],{},"Can I navigate this screen with headings and landmarks alone?",[264,1184,1185],{},"Are all interactive controls real controls?",[264,1187,1188],{},"Do form fields have discoverable names?",[264,1190,1191],{},"Did I introduce a “fake” element because CSS was annoying?",[15,1193,1194,1195,1198,1199,1202],{},"Annoying CSS is a ",[217,1196,1197],{},"you"," problem. Broken structure is a ",[217,1200,1201],{},"user"," problem.",[242,1204,1206],{"id":1205},"closing-thought","Closing Thought",[15,1208,1209],{},"Div soup isn’t a crime. Every developer has written it at some point.",[15,1211,1212],{},"But staying there is a missed opportunity.",[15,1214,1215],{},"Semantic HTML isn’t about being “correct” or “by the book.” It’s about making your code more understandable, more accessible, and more maintainable.",[15,1217,1218],{},"In a field where complexity is always increasing, anything that makes systems easier to understand is worth taking seriously.",[15,1220,1221,1222,1224,1225],{},"So next time you reach for a ",[22,1223,64],{},", take half a second and ask: ",[217,1226,1227],{},"“Is this really just a box?”",[15,1229,1230],{},"Sometimes it is.",[15,1232,1233],{},"But more often than not, it’s something more — and HTML already has a word for it.",[15,1235,1236,1237,1240,1241,1244,1245,75],{},"If you wouldn’t ship a REST API where every field was named ",[22,1238,1239],{},"data"," and ",[22,1242,1243],{},"thing",", don’t ship a page where every region is ",[22,1246,962],{},[15,1248,1249],{},"Structure is part of the product. Treat it that way.",[1251,1252,1253],"style",{},"html pre.shiki code .sGPm4, html code.shiki .sGPm4{--shiki-default:#81A1C1}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 pre.shiki code .sX7Mg, html code.shiki .sX7Mg{--shiki-default:#8FBCBB}html pre.shiki code .sNYnk, html code.shiki .sNYnk{--shiki-default:#ECEFF4}html pre.shiki code .sUFv7, html code.shiki .sUFv7{--shiki-default:#A3BE8C}html pre.shiki code .s0_w5, html code.shiki .s0_w5{--shiki-default:#D8DEE9FF}html pre.shiki code .st_Lx, html code.shiki .st_Lx{--shiki-default:#88C0D0}",{"title":48,"searchDepth":130,"depth":130,"links":1255},[1256,1257,1258,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277],{"id":244,"depth":111,"text":245},{"id":302,"depth":111,"text":303},{"id":478,"depth":111,"text":479,"children":1259},[1260,1261,1262],{"id":486,"depth":130,"text":487},{"id":574,"depth":130,"text":575},{"id":615,"depth":130,"text":616},{"id":643,"depth":111,"text":644},{"id":669,"depth":111,"text":670},{"id":729,"depth":111,"text":730},{"id":765,"depth":111,"text":766},{"id":799,"depth":111,"text":800},{"id":827,"depth":111,"text":828},{"id":883,"depth":111,"text":884},{"id":923,"depth":111,"text":924},{"id":968,"depth":111,"text":969},{"id":993,"depth":111,"text":994},{"id":1035,"depth":111,"text":1036},{"id":1121,"depth":111,"text":1122},{"id":1140,"depth":111,"text":1141},{"id":1173,"depth":111,"text":1174},{"id":1205,"depth":111,"text":1206},null,"Why your div-heavy markup hurts accessibility, SEO, and maintainability — and why choosing elements for what things *are* beats styling-first thinking.","md",{},true,"\u002Fblog\u002Fposts\u002Faccessibility\u002Fsemantic-html-beyond-divs","2026-04-12","9 min",{"title":9,"description":1279},"semantic-html-beyond-divs","blog\u002Fposts\u002Faccessibility\u002Fsemantic-html-beyond-divs","accessibility","post","p9THImc5V0cWxH3FY9i7cPK85ltEIVbV6B40udjLxVM",[1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313],{"id":244,"text":245,"depth":111},{"id":302,"text":303,"depth":111},{"id":478,"text":479,"depth":111},{"id":486,"text":487,"depth":130},{"id":574,"text":575,"depth":130},{"id":615,"text":616,"depth":130},{"id":643,"text":644,"depth":111},{"id":669,"text":670,"depth":111},{"id":729,"text":730,"depth":111},{"id":765,"text":766,"depth":111},{"id":799,"text":800,"depth":111},{"id":827,"text":828,"depth":111},{"id":883,"text":884,"depth":111},{"id":923,"text":924,"depth":111},{"id":968,"text":969,"depth":111},{"id":993,"text":994,"depth":111},{"id":1035,"text":1036,"depth":111},{"id":1121,"text":1122,"depth":111},{"id":1140,"text":1141,"depth":111},{"id":1173,"text":1174,"depth":111},{"id":1205,"text":1206,"depth":111},1777290096576]