Standards: SVG 2 Accessibility Standards - bounswe/bounswe2024group11 GitHub Wiki
2.1.1 All SVG images within the web application shall comply with SVG 2 Standards to ensure they are accessible, especially for users relying on assistive technologies. SVGs should include descriptive information and follow best practices for accessible implementation.
The abstract applies to inline SVG but it's better to keep it consistent with the external SVG's loaded asynchronously as <img>
source.
The goal of this requirement is to ensure that SVG images in the web application are accessible to all users, including those with disabilities. This includes clear labeling, descriptions, and integration with the document’s accessibility tree. SVG images should have appropriate keyboard navigation, descriptions, and should not be directly used as interactive elements but should be wrapped within accessible elements such as <button>
or <a>
.
Using descriptive attributes like <title>
and <desc>
is important for accessibility, as they provide context and understanding for the SVG content. For example, a <title>
with text like "Application Logo" helps users understand what the image represents.
SVGs should not be relied upon for interactive roles, such as buttons, as they do not natively support keyboard accessibility. Instead, SVGs should be wrapped with an accessible interactive element, such as a button, that includes ARIA roles as needed.
- Avoid using SVG filters unless absolutely necessary, as they can be computationally expensive.
- Ensure SVGs contain only vector data without raster images, as raster images cannot scale properly and may hinder accessibility.
- Each SVG image should be wrapped in a
<figure>
element or marked witharia-hidden="true"
if purely decorative. - Avoid using SVGs directly as clickable elements. Instead, wrap them with a
<button>
or<a>
element.
Relevant Tags
-
<svg>
: Defines the SVG container element. -
<title>
: Provides a text description for the SVG that assistive technologies can interpret. -
<desc>
: Adds a more detailed description for the SVG, often used for complex images. -
<use>
: Reuses a defined SVG element within the document. -
<g>
: Groups SVG elements together for accessibility grouping. -
<path>
: Draws shapes and paths within the SVG. -
<circle>
: Draws a circle within the SVG. -
<rect>
: Draws a rectangle within the SVG. -
<line>
: Draws a straight line within the SVG. -
<ellipse>
: Draws an ellipse within the SVG. -
<polygon>
: Draws a shape with multiple straight lines within the SVG. -
<polyline>
: Draws a series of connected straight lines within the SVG.
-
aria-hidden
: Hides SVG elements from assistive technologies when set to "true". -
role="img"
: Used to identify SVGs as images in the accessibility tree. -
aria-labelledby
: Associates the SVG with a visible or descriptive label. -
aria-describedby
: Provides a more detailed description that screen readers can access.
- Icon representing "Start Quiz" (SVG wrapped in
<button>
) - SVG illustration for quiz results (informational, not interactive)
- SVG icon representing "Bookmark Forum" (SVG wrapped in
<button>
) - Decorative SVG banner image (aria-hidden="true")
- All SVGs must include a
<title>
tag to provide a description accessible to assistive technologies. - Any SVG used for decorative purposes should include
aria-hidden="true"
to remove it from the accessibility tree. - SVG images should avoid raster graphics and rely solely on vector-based shapes and paths.
- All SVGs intended for interaction should be wrapped within an interactive element (e.g.,
<button>
or<a>
) and should not have event listeners attached directly to the SVG itself.
-
<title>
: Provides an accessible name that screen readers can interpret. -
role="img"
: Indicates that the SVG serves as an image. -
aria-labelledby
: Provides a label that is accessible to screen readers. -
aria-describedby
: Offers a description that screen readers can interpret.
- Avoid excessive use of filters or complex transformations, as these can impact accessibility and performance.
- Avoid embedding raster data, which can negatively affect the scalability and quality of SVG images.
<svg width=40 height=40 viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg" aria-labelledby="logoTitle">
<title id="logo-title">Turquiz</title>
<use href="#logo-shape" />
</svg>
<defs>
<g id="logo-shape" filter="url(#filter0_i_487_5349)">
<rect width="40" height="40" rx="20" fill="#5BADCE" />
<path d="M20.0008 23.2534C19.1826 21.9337 18.067 20.818 16.7473 19.9999C18.067 19.1817 19.1826 18.066 20.0008 16.7463C20.819 18.066 21.9346 19.1817 23.2544 19.9999C21.9346 20.818 20.819 21.9337 20.0008 23.2534Z" fill="url(#paint0_linear_487_5349)" stroke="url(#paint1_linear_487_5349)" />
<g filter="url(#filter1_d_487_5349)">
<path d="M33.2964 19C32.8095 12.4334 27.5666 7.1905 21 6.70361V11.4667C21 15.6272 24.3727 19 28.5333 19H33.2964Z" fill="url(#paint2_linear_487_5349)" fillOpacity="0.8" />
<path d="M21.5 11.4667V7.25337C27.3886 7.93871 32.0613 12.6114 32.7466 18.5H28.5333C24.6489 18.5 21.5 15.3511 21.5 11.4667Z" stroke="url(#paint3_linear_487_5349)" />
</g>
<g filter="url(#filter2_d_487_5349)">
<path d="M18.9995 6.70361C12.4329 7.1905 7.19001 12.4334 6.70312 19H11.4662C15.6267 19 18.9995 15.6272 18.9995 11.4667V6.70361Z" fill="url(#paint4_linear_487_5349)" fillOpacity="0.8" />
<path d="M11.4662 18.5H7.25288C7.93822 12.6114 12.6109 7.93871 18.4995 7.25337V11.4667C18.4995 15.3511 15.3506 18.5 11.4662 18.5Z" stroke="url(#paint5_linear_487_5349)" />
</g>
<path d="M28.5333 21.5H32.7466C32.0613 27.3886 27.3886 32.0613 21.5 32.7466V28.5333C21.5 24.6489 24.6489 21.5 28.5333 21.5Z" fill="url(#paint6_linear_487_5349)" fillOpacity="0.8" stroke="url(#paint7_linear_487_5349)" />
<path d="M18.4995 28.5333V32.7466C12.6109 32.0613 7.93822 27.3886 7.25288 21.5H11.4662C15.3506 21.5 18.4995 24.6489 18.4995 28.5333Z" fill="url(#paint8_linear_487_5349)" fillOpacity="0.8" stroke="url(#paint9_linear_487_5349)" />
</g>
</defs>
<defs>
<filter id="filter0_i_487_5349" x="0" y="0" width="44" height="44" filterUnits="userSpaceOnUse">
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape" />
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="4" dy="4" />
<feGaussianBlur stdDeviation="6" />
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.2 0" />
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_487_5349" />
</filter>
<filter id="filter1_d_487_5349" x="16.5556" y="6.70361" width="16.7413" height="20.0742" filterUnits="userSpaceOnUse">
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="-2.22222" dy="5.55556" />
<feGaussianBlur stdDeviation="1.11111" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix type="matrix" values="0 0 0 0 0.1728 0 0 0 0 0.64384 0 0 0 0 0.7872 0 0 0 0.32 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_487_5349" />
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_487_5349" result="shape" />
</filter>
<filter id="filter2_d_487_5349" x="6.70312" y="6.70361" width="16.7413" height="20.0742" filterUnits="userSpaceOnUse">
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="2.22222" dy="5.55556" />
<feGaussianBlur stdDeviation="1.11111" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix type="matrix" values="0 0 0 0 0.172549 0 0 0 0 0.643137 0 0 0 0 0.788235 0 0 0 0.32 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_487_5349" />
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_487_5349" result="shape" />
</filter>
<linearGradient id="paint0_linear_487_5349" x1="20.0008" y1="15.7217" x2="20.0008" y2="28.6961" gradientUnits="userSpaceOnUse">
<stop offset="0.313079" stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient id="paint1_linear_487_5349" x1="35.1035" y1="-5.04556" x2="9.92868" y2="15.3774" gradientUnits="userSpaceOnUse">
<stop stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient id="paint2_linear_487_5349" x1="27.1482" y1="6.70361" x2="27.1482" y2="25.3493" gradientUnits="userSpaceOnUse">
<stop offset="0.313079" stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient id="paint3_linear_487_5349" x1="48.8525" y1="-23.1413" x2="12.6734" y2="6.20879" gradientUnits="userSpaceOnUse">
<stop stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient id="paint4_linear_487_5349" x1="12.8513" y1="6.70361" x2="12.8513" y2="25.3493" gradientUnits="userSpaceOnUse">
<stop offset="0.313079" stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient id="paint5_linear_487_5349" x1="34.5557" y1="-23.1413" x2="-1.62345" y2="6.20885" gradientUnits="userSpaceOnUse">
<stop stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient id="paint6_linear_487_5349" x1="27.1482" y1="21" x2="27.1482" y2="39.6457" gradientUnits="userSpaceOnUse">
<stop offset="0.313079" stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient id="paint7_linear_487_5349" x1="48.8525" y1="-8.84483" x2="12.6734" y2="20.5052" gradientUnits="userSpaceOnUse">
<stop stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient id="paint8_linear_487_5349" x1="12.8513" y1="21" x2="12.8513" y2="39.6457" gradientUnits="userSpaceOnUse">
<stop offset="0.313079" stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
<linearGradient id="paint9_linear_487_5349" x1="34.5557" y1="-8.84483" x2="-1.62342" y2="20.5053" gradientUnits="userSpaceOnUse">
<stop stopColor="white" />
<stop offset="1" stopColor="white" stopOpacity="0" />
</linearGradient>
</defs>
- Even though the guidelines say not to use SVG filters unless necessary, for our logo implementation, we found that using a filter produced significantly better results than the exported PNG, which was consuming excessive space. In this specific case, the filter approach proved to be the more practical solution.