{"id":19878885,"url":"https://github.com/gtap-dev/html","last_synced_at":"2026-03-05T01:34:59.448Z","repository":{"id":48857416,"uuid":"287518877","full_name":"gtap-dev/html","owner":"gtap-dev","description":null,"archived":false,"fork":false,"pushed_at":"2021-07-08T11:38:39.000Z","size":10,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-01T02:34:27.526Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gtap-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-08-14T11:37:49.000Z","updated_at":"2021-07-08T11:38:38.000Z","dependencies_parsed_at":"2022-09-03T14:21:57.840Z","dependency_job_id":null,"html_url":"https://github.com/gtap-dev/html","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gtap-dev/html","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtap-dev%2Fhtml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtap-dev%2Fhtml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtap-dev%2Fhtml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtap-dev%2Fhtml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gtap-dev","download_url":"https://codeload.github.com/gtap-dev/html/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtap-dev%2Fhtml/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30104667,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T01:06:53.091Z","status":"ssl_error","status_checked_at":"2026-03-05T01:02:35.679Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T17:06:59.047Z","updated_at":"2026-03-05T01:34:59.414Z","avatar_url":"https://github.com/gtap-dev.png","language":null,"readme":"# Twig \u0026 HTML `\u003cguide-lines /\u003e`\n\n*A mostly reasonable approach to Twig*\n\nThis is a superset of the [Official SensioLabs Twig Standards](https://twig.symfony.com/doc/1.x/coding_standards.html).\n\n## Resources\n\n- [Twig docs](https://twig.symfony.com/doc/1.x/).\n\n## Filters\n\n\u003ca name=\"replace-string-tokens\"\u003e\u003ca name=\"2.1\"\u003e\u003c/a\u003e\n  - [2.1]() String tokens to be used inside the `replace` filter should be\n    marked with percentage signs.\n\n    ```twig\n    {# Bad #}\n    {{ sidekicks|replace('{{ robin }}', 'Dick Grayson') }}\n\n    {# Good #}\n    {{ sidekicks|replace('%robin%', 'Jason Todd') }}\n    ```\n\n\u003ca name=\"default-data-logic\"\u003e\u003ca name=\"2.2\"\u003e\u003c/a\u003e\n  - [2.2]() Do not use the default filter for default data.\n\n    Default data should come from context. Use default filter for logic only.\n\n    ```twig\n    {# Bad #}\n    {{ url|default('#') }}\n\n    {# Good #}\n    {{ url|default(data.url) }}\n    ```\n\n\u003ca name=\"merge-filter\"\u003e\u003ca name=\"2.3\"\u003e\u003c/a\u003e\n  - [2.3]() Use merge filter to add to arrays or objects.\n\n    Note that you need to make sure the array/object is iterable.\n\n    ```twig\n    {# Bad #}\n    {% include '@button' with { data: { text: data.button.text, icon: '#arrow-right' } } %}\n\n    {# Good #}\n    {% include '@button' with { data: data.button|merge({ icon: '#arrow-right' }) } %}\n    ```\n\n\u003ca name=\"escape-filter\"\u003e\u003ca name=\"2.4\"\u003e\u003c/a\u003e\n  - [2.4]() Escape data and values in HTML attributes with the `escape` filter.\n\n    ```twig\n    {# Bad #}\n    \u003cbutton data-name=\"{{ data.name }}\"\u003e\n\n    {# Good #}\n    \u003cbutton data-name=\"{{ data.name|escape('html_attr') }}\"\u003e\n    ```\n\n\u003ca name=\"avoid-filters\"\u003e\u003ca name=\"2.5\"\u003e\u003c/a\u003e\n  - [2.5]() If possible, avoid transforming data with filters. Transform data beforehand, in PHP.\n\n## Functions\n\n\u003ca name=\"dump-function\"\u003e\u003ca name=\"3.1\"\u003e\u003c/a\u003e\n  - [3.1]() Use dump function to debug data.\n\n    Wrap the output with a `pre` tag to make it easier to read.\n\n    ```twig\n    \u003cpre\u003e\n      {{ dump(user) }}\n    \u003c/pre\u003e\n    ```\n\n## Operators\n\n\u003ca name=\"do-not-use-math\"\u003e\u003ca name=\"4.1\"\u003e\u003c/a\u003e\n  - [4.1]() Do not use Math operators.\n\n    Math is calculation logic that should stay in PHP.\n\n    As an example, instead of the mod operator, use batching.\n    ```twig\n    {# Bad #}\n    {% for row in items %}\n      {% if loop.index == 1 or (loop.index % 3) == 1 %}\n        {# do something with every third item #}\n      {% endif %}\n    {% endfor %}\n\n    {# Good #}\n    {% for row in items|batch(3) %}\n      {% for column in row %}\n        {% if loop.index == 1 %}\n          {# do something with every third item #}\n        {% endif %}\n      {% endfor %}\n    {% endfor %}\n    ```\n\n\n## Variables\n\n\u003ca name=\"use-set-tags-for-variables\"\u003e\u003ca name=\"5.1\"\u003e\u003c/a\u003e\n  - [5.1]() Use variables to store common values in templates.\n\n    Instead of doing the same template logic in multiple instances, save the values to variables with `set` tags.\n\n## Comments\n\n\u003ca name=\"use-set-tags-for-variables\"\u003e\u003ca name=\"6.1\"\u003e\u003c/a\u003e\n  - [6.1]() Use Twig comments to convey important implementation information to other developers.\n\n    Twig comments will be compiled away, HTML comments are transferred and visible in source to all users.\n\n    ```twig\n    {# Bad #}\n    \u003c!-- TODO: id should not be static --\u003e\n    \u003cinput id=\"input-1\" /\u003e\n\n    {# Good #}\n    {# TODO: id should not be static #}\n    \u003cinput id=\"input-1\" /\u003e\n    ```\n\n## Whitespace\n\n  \u003ca name=\"whitespace--before-blocks\"\u003e\u003c/a\u003e\u003ca name=\"9.1\"\u003e\u003c/a\u003e\n  - [9.1](#whitespace--before-blocks) Place 1 space before the leading brace.\n\n    ```twig\n    {# Bad #}\n    {% set dog={\n        'age': '1 year',\n        'breed': 'Bernese Mountain Dog',\n    } %};\n\n    {# Good #}\n    {% set dog = {\n        'age': '1 year',\n        'breed': 'Bernese Mountain Dog',\n    } %};\n    ```\n\n  \u003ca name=\"whitespace--around-keywords\"\u003e\u003c/a\u003e\u003ca name=\"9.2\"\u003e\u003c/a\u003e\n  - [9.2](#whitespace--around-keywords) Place 1 space before the opening\n    parenthesis in control statements (`if`, `for` etc.). Place no space\n    between the argument list and the function name in function calls and\n    declarations.\n\n    ```twig\n    {# Bad #}\n    {% if(isJedi) %}\n        {% set enemy = 'sith' %}\n    {% endif %}\n\n    {# Good #}\n    {% if (isJedi) %}\n        {% set enemy = 'sith' %}\n    {% endif %}\n\n    {# Bad #}\n    {{ jedi|default ('Yoda') }}\n\n    {# Good #}\n    {{ jedi|default('Yoda') }}\n    ```\n\n  \u003ca name=\"whitespace--infix-ops\"\u003e\u003c/a\u003e\u003ca name=\"9.3\"\u003e\u003c/a\u003e\n  - [9.3](#whitespace--infix-ops) Set off operators with spaces.\n\n    ```twig\n    {# Bad #}\n    {% set x=y+5 %}\n\n    {# Good #}\n    {% set x = y + 5 %}\n    ```\n\n  \u003ca name=\"whitespace--newline-at-end\"\u003e\u003c/a\u003e\u003ca name=\"9.4\"\u003e\u003c/a\u003e\n  - [9.4](#whitespace--newline-at-end) End files with a single newline\n    character.\n\n    ```twig\n    {# Bad #}\n    {{ stuff }}\n    ```\n\n    ```twig\n    {# Bad #}\n    {{ stuff }}↵\n    ↵\n    ```\n\n    ```twig\n    {# Good #}\n    {{ stuff }}↵\n    ```\n\n  \u003ca name=\"whitespace--padded-blocks\"\u003e\u003c/a\u003e\u003ca name=\"9.5\"\u003e\u003c/a\u003e\n  - [9.5](#whitespace--padded-blocks) Do not pad your blocks with blank lines.\n\n    ```twig\n    {# Bad #}\n    {%\n\n      set foo = 'bar'\n\n    %}\n\n    {# Bad #}\n    {% if baz %}\n\n      {{ qux }}\n    {% elseif %}\n      {{ foo }}\n\n    {% endif %}\n\n    {# Good #}\n    {% if baz %}\n      {{ qux }}\n    {% elseif %}\n      {{ foo }}\n    {% endif %}\n    ```\n\n  \u003ca name=\"whitespace--in-parens\"\u003e\u003c/a\u003e\u003ca name=\"9.6\"\u003e\u003c/a\u003e\n  - [9.6](#whitespace--in-parens) Do not add spaces inside parentheses.\n\n    ```twig\n    {# Bad #}\n    {{ foo|default( 'foo' ) }}\n\n    {# Good #}\n    {{ foo|default('foo') }}\n    ```\n\n  \u003ca name=\"whitespace--in-brackets\"\u003e\u003c/a\u003e\u003ca name=\"9.7\"\u003e\u003c/a\u003e\n  - [9.7](#whitespace--in-brackets) Do not add spaces inside brackets.\n\n    ```twig\n    {# Bad #}\n    {% set foo = [ 1, 2, 3 ] %}\n    {{ foo.0 }}\n\n    {# Good #}\n    {% set foo = [1, 2, 3] %}\n    {{ foo.0 }}\n    ```\n\n  \u003ca name=\"whitespace--in-braces\"\u003e\u003c/a\u003e\u003ca name=\"9.10\"\u003e\u003c/a\u003e\n  - [9.8](#whitespace--in-braces) Add spaces inside curly braces.\n\n    ```twig\n    {# Bad #}\n    {% set foo = {clark: 'kent'} %}\n\n    {# Good #}\n    {% set foo = { clark: 'kent' } %}\n    ```\n\n  \u003ca name=\"whitespace--max-len\"\u003e\u003c/a\u003e\u003ca name=\"9.9\"\u003e\u003c/a\u003e\n  - [9.9](#whitespace--max-len) Avoid having everything in one line.\n\n    \u003e Why? This ensures readability and maintainability.\n\n    ```twig\n    {# Bad #}\n    {% if victory|default %}{{ congratulations }}{% else %}{{ failure }}{% endif %}\n\n    {# Good #}\n    {% if victory|default %}\n        {{ congratulations }}\n    {% else %}\n        {{ failure }}\n    {% endif %}\n    ```\n\n  \u003ca name=\"whitespace--attributes\"\u003e\u003c/a\u003e\u003ca name=\"9.10\"\u003e\u003c/a\u003e\n  - [9.10](#whitespace--attributes) Avoid having too much attributes in single line.\n\n    \u003e Why? This ensures readability and maintainability.\n\n    ```twig\n    {# Bad #}\n    \u003cimg loading=\"lazy\" src=\"{{ placeholderSrc }}\" data-srcset=\"{{ data.srcset }}\" data-sizes=\"auto\" alt=\"{{ data.alt }}\" {% if data.width %}width=\"{{ data.width }}\"{% endif %} {% if data.title %}title=\"{{ data.title }}\"{% endif %} class=\"image__img lazyload\"\u003e\n\n    {# Good #}\n    \u003cimg\n        loading=\"lazy\"\n        src=\"{{ placeholderSrc }}\"\n        data-srcset=\"{{ data.srcset }}\"\n        data-sizes=\"auto\"\n        alt=\"{{ data.alt }}\"\n        {% if data.width %}width=\"{{ data.width }}\"{% endif %}\n        {% if data.title %}title=\"{{ data.title }}\"{% endif %}\n        class=\"image__img lazyload\"\n    \u003e\n    ```\n\n  \u003ca name=\"whitespace--single-attribute\"\u003e\u003c/a\u003e\u003ca name=\"9.11\"\u003e\u003c/a\u003e\n  - [9.11](#whitespace--single-attribute) Avoid having too much logic in a single HTML attribute.\n\n    \u003e Why? This ensures readability and maintainability.\n\n    Instead, split the logic to a separate variable block with whitespace control.\n\n    ```twig\n    {# Bad #}\n    \u003cdiv class=\"textfield{% if modifier %} {{ modifier }}{% endif %}{% if class %} {{ class }}{% endif %}{% if data.isInvalid %} is-invalid{% endif %}{% if data.isDisabled %} is-disabled{% endif %}{% if data.icon %} textfield--icon{% endif %}\"\u003e\u003c/div\u003e\n\n    {# Good #}\n    {% set BEM -%}\n      textfield\n      {% if modifier %} {{ modifier }}{% endif %}\n      {%- if class %} {{ class }}{% endif %}\n      {%- if data.isInvalid %} is-invalid{% endif %}\n      {%- if data.isDisabled %} is-disabled{% endif %}\n      {%- if data.icon %} textfield--icon{% endif %}\n    {% endset %}\n    \u003cdiv class=\"{{ BEM }}\"\u003e\u003c/div\u003e\n    ```\n\n\u003ca name=\"whitespace--indenting\"\u003e\u003c/a\u003e\u003ca name=\"9.12\"\u003e\u003c/a\u003e\n  - [9.12](#whitespace--indenting) Indenting nested logic and blovks\n\n    For consistency, everything that is nested should be indented by one level more than its context. (Even if it breaks HTML indentation)\n\n    ```twig\n    {# Bad #}\n    {% if data.title %}\n    {{ data.title }}\n    {% endif %}\n\n    \u003cdiv class=\"row__one\"\u003e{{ data.rowOne }}\u003c/div\u003e\n    {% if data.rowTwo %}\n    \u003cdiv class=\"row__two\"\u003e{{ data.rowTwo }}\u003c/div\u003e\n    {% endif %}\n\n    {# Good #}\n    {% if data.title %}\n        {{ data.title }}\n    {% endif %}\n\n    \u003cdiv class=\"row__one\"\u003e{{ data.rowOne }}\u003c/div\u003e\n    {% if data.rowTwo %}\n        \u003cdiv class=\"row__two\"\u003e{{ data.rowTwo }}\u003c/div\u003e\n    {% endif %}\n    ```\n\n## Stylistic rules\n\n\u003ca name=\"styles--leading-trailing\"\u003e\u003c/a\u003e\u003ca name=\"10.1\"\u003e\u003c/a\u003e\n  - [10.1](#styles--leading-trailing) Leading commas: **No.**\n\n    ```twig\n    {# Bad #}\n    {% set story = [\n      'once'\n    , 'upon'\n    , 'a'\n    , 'time'\n    ] %}\n\n    {# Good #}\n    {% set story = [\n      once,\n      upon,\n      aTime,\n    ] %}\n\n    {# Bad #}\n    {% set hero = {\n        'firstName': 'Ada'\n      , 'lastName': 'Lovelace'\n      , 'birthYear': '1815'\n      , 'superPower': 'computers'\n    } %}\n\n    {# Good #}\n    {% set hero = {\n      'firstName': 'Ada',\n      'lastName': 'Lovelace',\n      'birthYear': '1815',\n      'superPower': 'computers'\n    } %}\n    ```\n\n\u003ca name=\"styles--quotes\"\u003e\u003c/a\u003e\u003ca name=\"10.2\"\u003e\u003c/a\u003e\n  - [10.2](#styles--quotes) Use double quotes for HTML attributes, single quotes for everything else.\n\n    ```twig\n    {# Bad #}\n    \u003cinput value='bad' /\u003e\n\n    {# Good #}\n    \u003cinput value=\"good\" /\u003e\n    \u003cinput value=\"\\\"good\\\"\" /\u003e\n\n    {# Bad #}\n    {% set hero = \"bad\" %}\n\n    {# Good #}\n    {% set hero = 'good' %}\n    ```\n\n## Naming conventions\n\n  - [11.1](#naming-camelCase) Use camelCase to name variables.\n\n    ```twig\n    {# Bad #}\n    {% set story_of_my_life = 'cry baby cry' %}\n    {% set storyofmylife = 'cry baby cry' %}\n\n    {# Good #}\n    {% set storyOfMyLife = 'cry baby cry' %}\n    ```\n\n## Known issues\n\nYou can use majority of twig functions, but there are some restrictions in styleguide, because we use Twig.js adapter.\n\n\u003ca name=\"known-issues--macro\"\u003e\u003c/a\u003e\u003ca name=\"13.1\"\u003e\u003c/a\u003e\n  - [13.1](#known-issues--macro) Include inside macro not working very well. Example:\n\n    ```twig\n    {% macro li(item, class, icon) %}\n        \u003cli class=\"pagination__item {{ class }}\"\u003e\n            \u003ca href=\"{{ item.url }}\" class=\"pagination__link\"\u003e\n                {% include '@icon' with { name: icon } %}\n                {{ item.text }}\n            \u003c/a\u003e\n        \u003c/li\u003e\n    {% endmacro %}\n\n    {{ ul.li(data.item, 'pagination__item--first', 'arrow') }}\n    ```\n\n    You can fix this issue by sending whole icon component into macro. Example:\n\n    ```twig\n        {% macro li(item, class, icon) %}\n            \u003cli class=\"pagination__item {{ class }}\"\u003e\n                \u003ca href=\"{{ item.url }}\" class=\"pagination__link\"\u003e\n                    {{ icon }}\n                    {{ item.text }}\n                \u003c/a\u003e\n            \u003c/li\u003e\n        {% endmacro %}\n\n        {% set icon %}\n            {% include '@icon' with { name: 'arrow' } %}\n        {% endset %}\n        {{ ul.li(data.item, 'pagination__item--first', icon) }}\n    ```\n\n    It's not nice but will work.\n\n## General\n\n\u003ca name=\"general--twig-php-and-js\"\u003e\u003ca name=\"14.1\"\u003e\u003c/a\u003e\n  - [14.1]() When deciding to choose whether to use a certain Twig functionality, make sure it is supported by both Twig PHP and [Twig.js](https://github.com/twigjs/twig.js) as we generally use both in our projects.\n\n\u003ca name=\"general--if-wrapping\"\u003e\u003c/a\u003e\u003ca name=\"14.2\"\u003e\u003c/a\u003e\n  - [14.2](#general--if-wrapping) If data existence is questionable, use twig if tag.\n\n    ```twig\n    {# Bad #}\n    \u003cdiv class=\"textfield__error\"\u003e\n        {{ data.error }}\n    \u003c/div\u003e\n\n    {# Bad #}\n    \u003cdiv class=\"textfield__error\"\u003e\n        {% if data.error %}\n            {{ data.error }}\n        {% endif %}\n    \u003c/div\u003e\n\n    {# Good (no unnecessary html) #}\n    {% if data.error %}\n        \u003cdiv class=\"textfield__error\"\u003e\n            {{ data.error }}\n        \u003c/div\u003e\n    {% endif %}\n    ```\n\n\u003ca name=\"general--use-data\"\u003e\u003c/a\u003e\u003ca name=\"14.3\"\u003e\u003c/a\u003e\n  - [14.3](#general--use-data) Use data.something only if data really comes from back-end and is changeable\n\n    ```twig\n    Example if button icon is fixed and admin can't change it.\n\n    \u003cbutton type=\"button\"\u003e\n        {{ data.text }}\n        {% include '@icon' with { name: icon, class: 'button__icon', modifier: '' } %}\n    \u003c/button\u003e\n    ```\n\n## HTML\n\n\u003ca name=\"html--semantics\"\u003e\u003ca name=\"15.1\"\u003e\u003c/a\u003e\n  - [15.1](#html--semantics) Use semantic [HTML elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element), wherever appropriate.\n\n    This is to ensure basic usability of the website for all people.\n\n    ```twig\n    {# Bad #}\n    {# Clickable div that does not have role button nor is tabbable. #}\n    \u003cdiv onclick=\"\"\u003e\n        {{ data.text }}\n    \u003c/div\u003e\n    \u003ca href=\"#\"\u003ethis is a button that has interactivity via JS and no real href\u003c/a\u003e\n\n    {# Good #}\n    \u003cbutton onclick=\"\"\u003e\n        {{ data.text }}\n    \u003c/button\u003e\n    \u003cbutton\u003ethis is a button that has interactivity via JS\u003c/button\u003e\n    ```\n\n\u003ca name=\"html--landmarks\"\u003e\u003ca name=\"15.2\"\u003e\u003c/a\u003e\n  - [15.2](#html--landmarks) Use appropriate landmarks to convey important parts of the website to assistive tech.\n\n    See examples in [WAI-ARIA Authoring Practises](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_landmark).\n\n\n\u003ca name=\"html--semantic-content-order\"\u003e\u003ca name=\"15.3\"\u003e\u003c/a\u003e\n  - [15.3](#html--semantic-content-order) Make sure your content order is semantic.\n\n    Sometimes due to design quirks HTML structure cannot be semantically correct. In these cases you can hide the wrongfully placed elements using `aria-hidden=\"true\"` and add visually hidden elements to semantically appropriate places, thus making content order correct and accessible.\n\n    ```twig\n    {# Bad #}\n    \u003csection\u003e\n        \u003cdiv class=\"content\"\u003e...\u003c/div\u003e\n        \u003ch2\u003eSection title\u003c/h2\u003e\n        \u003cdiv class=\"content\"\u003e...\u003c/div\u003e\n    \u003c/section\u003e\n\n    {# Better #}\n    \u003csection\u003e\n        \u003ch2 class=\"h-visually-hidden\"\u003eSection title\u003c/h2\u003e\n        \u003cdiv class=\"content\"\u003e...\u003c/div\u003e\n        \u003ch2 aria-hidden=\"true\"\u003eSection title\u003c/h2\u003e\n        \u003cdiv class=\"content\"\u003e...\u003c/div\u003e\n    \u003c/section\u003e\n\n    {# Best #}\n    {# Work with your designer to make sure the design order follows semantic order! #}\n    \u003csection\u003e\n        \u003ch2\u003eSection title\u003c/h2\u003e\n        \u003cdiv class=\"content\"\u003e...\u003c/div\u003e\n        \u003cdiv class=\"content\"\u003e...\u003c/div\u003e\n    \u003c/section\u003e\n    ```\n\n\u003ca name=\"html--accessibility\"\u003e\u003ca name=\"15.4\"\u003e\u003c/a\u003e\n  - [15.4](#html--accessibility) Use appropriate ARIA behavior on interactive components that do not exist natively in HTML.\n\n    For example: alerts, dialogs, tooltips, accordions, tabs, autocomplete inputs do not have native HTML elements that convey their behavior and semantics to assistive technology.\n\n    These kinds of interactive components need to have appropriate ARIA roles and JavaScript functionality to work properly for everyone.\n\n    Please explore the [WAI-ARIA Authoring Practises](https://www.w3.org/TR/wai-aria-practices-1.1/) document for specific examples and explanations.\n\n\u003ca name=\"html--target-blank\"\u003e\u003ca name=\"15.5\"\u003e\u003c/a\u003e\n  - [15.5](#html--target-blank) Avoid using `target=\"_blank\"` on links.\n\n    Do not force people to new tabs/windows when it is not strictly necessary. People who want to open links in new tabs usually know how to do this themselves.\n\n    See this [CSS-Tricks article](https://css-tricks.com/use-target_blank/) for more explanations.\n\n    If you absolutely must use `target=\"_blank\"` on links, use `rel=\"noreferrer` with it.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgtap-dev%2Fhtml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgtap-dev%2Fhtml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgtap-dev%2Fhtml/lists"}