npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@seznam/szn-select

v1.4.7

Published

Accessible HTML selectbox with customizable UI. Based on web components and easy to integrate with various frameworks like React or Angular.

Downloads

56

Readme

szn-select

npm License

Accessible HTML <select> element replacement with customizable UI. Based on the patterns used by web components and easy to integrate with various frameworks, e.g. React or Angular.

You can check out the demo or take a peek at a fiddle.

Usage

As the first rule of ARIA states: use the native <select> element if possible. If you can get by with the basic styling support the native <select> element has, please do not try to replace it, your users will have much better experience (this is the way the Bootstrap framework does it).

If you absolutely do need a fully styleable <select>, you may choose from the following integration-ready bundles based on the front-end technology you use:

More ready-to-use bundles are coming soon.

Usage on static or server-rendered websites

  1. Include the CSS for fallback styling of the native <select> element in case JavaScript is disabled or the user is using an obsolete browser:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@seznam/[email protected]/szn-select-nojs.css">

This step is optional, but results in slightly better UX if the JavaScript fails or is disabled.

  1. It is recommended to load the <szn-select> element using the loader:
<script src="https://cdn.jsdelivr.net/npm/@seznam/[email protected]/loader.min.js"></script>

It is recommended to use a semver version range when using jsdelivr, unpkg or a similar JS CDN, such as 1.x to automatically receive the latest compatible version with the most recent bugfixes and compatibility updates.

You may use the async and defer attributes if you want the loader to be loaded asynchronously. You may also bundle the loader with other JavaScript files.

The loader automatically chooses the bundle that has the best compatibility with the current browser (modern browsers use smaller bundles). By default the loader loads the implementation from jsdelivr.com. This may be overridden by adding the following attributes to the <script> element used include the loader (as stated above, this may be a bundle):

  • data-szn-select--loader-urls--package - specifies the base URL where all the package's files are available. This can be overridden for specific cases using the options listed below.
  • data-szn-select--loader-urls--es3 - overrides the URL for loading the ES3-compatible implementation of the szn-select element.
  • data-szn-select--loader-urls--es2016 - overrides the URL for loading the ES2016-compatible implementation of the szn-select element.
  • data-szn-select--loader-urls--bundle-elements-es3 - overrides the URL for loading the ES3-compatible implementation of the szn-select and szn-tethered element.
  • data-szn-select--loader-urls--bundle-elements-es2016 - overrides the URL for loading the ES2016-compatible implementation of the szn-select and szn-tethered element.
  • data-szn-select--loader-urls--bundle-full-es3 - overrides the URL for loading the ES3-compatible bundle of the szn-select and szn-tethered elements and the szn-elements runtime.
  • data-szn-select--loader-urls--bundle-full-es2016 - overrides the URL for loading the ES2016-compatible implementation of the szn-select and szn-tethered elements and the szn-elements runtime.
  • data-szn-select--loader-urls--bundle-full-ce - overrides the URL for loading the ES2016-compatible implementation that relies on the custom elements API. The bundle includes the szn-select and szn-tethered elements and the szn-elements runtime (only the parts used if custom elements are supported natively).

If you do not want to use the loader for some reason, just include the ES3-compatible bundle (or implement the bundle selection logic yourselves):

<script src="https://cdn.jsdelivr.net/npm/@seznam/[email protected]/szn-select.bundle-full.es3.min.js"></script>

Please note that using the loader has great advantages: the compatibility of various assistive technologies may and does change over time and the loader will attempt to load the latest backwards-compatible version for you to get the best compatibility. It is also recommended to use a version range (e.g. 1.x) when loading the loader from jsdelivr.com to get the latest compatible version of the loader itself.

  1. You may turn any ordinary <select> into a <szn-select> by wrapping it and providing a UI container:
<label for="my-select">Choose one:</label>
<szn-select data-szn-select--standalone>
    <select name="chosenOption" id="my-select">
        <option value="1" title="this is the first option">first</option>
        <optgroup label="other options">
            <option value="2" selected>default option</option>
            <option value="3" disabled>you cannot choose this option</option>
        </optgroup>
        <optgroup label="you cannot choose these options" disabled>
            <option value="4">unavailable option</option>
            <option value="4">yes, multiple options may have the same value</option>
        </optgroup>
    </select>
    <span data-szn-select--ui></span>
</szn-select>

The data-szn-select--standalone attribute tells the <szn-select> that is is not being used on a page that uses a DOM-managing library such as React, Vue or Angular.

The <szn-select> element works with multi-selects too:

<szn-select data-szn-select--standalone>
    <select name="choices" multiple aria-label="choose multiple">
        <option value="1" selected>first</option>
        <optgroup label="other options">
            <!-- option groups are supported as well -->
            <option value="2" disabled>second</option>
            <option value="3" selected>third</option>
        </optgroup>
    </select>
    <span data-szn-select--ui></span>
</szn-select>

Styling using CSS

The <szn-select> element's appearance can be configured using the following CSS variables (AKA CSS custom properties, supported by all browsers except for Internet Explorer):

:root {
  /* variable: default value */
  --szn-select--border-width: 1px;
  --szn-select--border-color: #cccccc;
  --szn-select--active-border-color: #7dbfff;
  --szn-select--border-radius: 4px;
  --szn-select--min-width: 109px;
  --szn-select--height: 2em;
  --szn-select--height-px: 32px;

  --szn-select--option-indent: 12px;
  --szn-select--option-padding: 5px 5px 5px var(--szn-select--option-indent);
  --szn-select--selected-option-background: #eeeeee;

  --szn-select--button-padding: 0 5px 0 var(--szn-select--option-indent);
  --szn-select--state-arrow-width: var(--szn-select--height);

  --szn-select--state-arrow-closed: "▼";
  --szn-select--state-arrow-opened: "▲";
  --szn-select--text-color: #000000;
  --szn-select--disabled-text-color: #cccccc;
  --szn-select--background: #ffffff;

  --szn-select--active-box-shadow: 0 0 3px rgba(0, 132, 255, .4);
}

To style the dimensions of the dropdown for single-selects, use the following CSS selector:

[data-szn-select--ui--dropdown] {
    /* overriding the dropdown's width to 240px for the default font size of 16px */
    width: 15rem;
}

The appearance of the options dropdown can be customized by setting the dropdownClassName property of the <szn-select> element:

<szn-select id="my-select">
  ...
</szn-select>
<script>
  document.getElementById('my-select').dropdownClassName = 'my-custom-dropdown'
</script>

This will configure this particular <szn-select> to set the my-custom-dropdown CSS class on its own options dropdown (the <szn-select--options> element). See the Instance configuration section below for all options.

With the custom CSS class set, your will now be able to override the look&feel of this particular select's dropdown without affecting the rest. One approach you may utilize is overriding the CSS custom properties configuring the look&feel - if you are not concerned about compatibility with Internet Explorer. The code below shows the default configuration specified in szn-select.css:

.my-custom-dropdown {
  --szn-select--options--border-width: var(--szn-select--border-width);
  --szn-select--options--border-color: var(--szn-select--border-color);
  --szn-select--options--border-radius-dropdown: 0 0 var(--szn-select--border-radius) var(--szn-select--border-radius);
  --szn-select--options--border-radius-dropup: var(--szn-select--border-radius) var(--szn-select--border-radius) 0 0;
  --szn-select--options--border-radius-mutli-select: var(--szn-select--border-radius);
  --szn-select--options--item-padding: var(--szn-select--option-padding);
  --szn-select--options--item-indent: var(--szn-select--option-indent);
  --szn-select--options--text-color: var(--szn-select--text-color);
  --szn-select--options--disabled-text: var(--szn-select--disabled-text-color);
  --szn-select--options--background-color: var(--szn-select--background);
  --szn-select--options--selected-background: var(--szn-select--selected-option-background);
  --szn-select--ui--dropdown-offset: calc(-1 * var(--szn-select--border-width));
  --szn-select--ui--dropdown-min-width: var(--szn-select--min-width);
}

Note that the styles used by the <szn-select> are applied using <style> elements appended the document's <head>. You will have to use selectors with higher specificity or use !important to override the default styles.

Instance configuration

Every <szn-select> element has several properties that configure the element's behavior. These options are not shared between <szn-select> elements:

  • minBottomSpace: number - the minimum height in pixels of area between the bottom of the <szn-select> and the bottom of the viewport for the dropdown to be displayed below the <szn-select>. The default value is 160.
  • dropdownClassName: string - the CSS class(es) to set on the wrapper element of the <szn-select>'s dropdown. This is used to apply custom styling to the dropdown without affecting the dropdowns of other <szn-select>s.
  • dropdownContainer: Node - the element into which the <szn-select> will append its dropdown UI when opened. This is document.body by default. Please note that <szn-select> will handle positioning the dropdown only if this is set to the default value, otherwise you will have to handle the positioning of the dropdown yourself.

Supported browsers

  • Chrome/Chromium
  • Firefox
  • Opera
  • Safari
  • Edge
  • Internet Explorer 9 - 11 (polyfill for IE8 is possible and in consideration)

Suppport of Microsoft Edge 16 and older, Internet Explorer 11 and older

You will need to include polyfills to make <szn-select> work in Internet Explorer. Chances are, if you are already using babel/webpack in your project, that you are already using the necessary polyfills. If, however, things do not work in IE/Edge, please include the babel polyfill (or the core-js polyfill itself) by adding the following code in the <head> element before including the <szn-select> element's JavaScript:

<script>
if (!window.WeakSet || !window.Proxy || !Array.prototype.includes) {
  document.write('<script src="https://cdn.jsdelivr.net/npm/[email protected]/browser.js"><\/script>')
}
</script>

This will include the polyfill only if the browser needs it, therefore the users of modern browsers won't be slowed down by downloading additional JavaScript that they don't need anyway.

Next you will need to include the polyfill for missing DOM APIs for IE 9-11 and Edge 12-16.

<script>
if (!("firstElementChild" in document.createDocumentFragment())) {
  document.write('<script src="https://cdn.jsdelivr.net/npm/@seznam/[email protected]/polyfill/modern-ie.min.js"><\/script>')
}
</script>

Microsoft Edge 17+ does not need any of these polyfills.

Support for IE 9 and 10

Internet Explorer 10 and older seems to have some issue with the minified version of the DOM API polyfill mentioned above, so, first, change the code to use the unminified version:

<script>
if (!("firstElementChild" in document.createDocumentFragment())) {
  document.write('<script src="https://cdn.jsdelivr.net/npm/@seznam/[email protected]/polyfill/modern-ie.js"><\/script>')
}
</script>

Internet Explorer 10 and older does not have support for the custom elements nor the MutationObserver, however, versions 9 and 10 support the (deprecated) DOM mutation events. This allows us to use the following polyfill to enable support for IE 9 and 10. Add the following code to the <head> element before including any other polyfills:

<script>
  if (!window.MutationObserver) {
    window.module = {} // required by the polyfill
    document.write('<script src="https://cdn.jsdelivr.net/npm/[email protected]/index.js"><\/script>')
  }
</script>

Current state of compatibility with assistive technologies

The current level of compatibility with assistive technologies is represented by the table below:

  | Chrome | Firefox | Opera | Safari | Edge | IE ---------------------------------------------------------------------------------------------|--------|---------|-------|--------|---------|--- keyboard | great | great | great | great | great | great NVDA | great | great | great | n/a | great | good Jaws | good | n/a | good | n/a | n/a | good VoiceOver | good | n/a | good | good | n/a | n/a Talkback | good | good | good | n/a | unknown | n/a VoiceOver iOS | good | good | n/a | good | unknown | n/a

Compatibility levels explained

compatibility | explanation --------------|------------ great | Usability on par with the native <select> element good | Minor issues (e.g. using the native dropdown on mobile platform) that have minimal impact on UX passable | The assistive technology might not recognize the szn-select as a combobox, does not announce the value automatically, or is sometimes silent, but still usable n/a | The combination is not compatible due to platform restrictions (e.g. NVDA is Windows-only) or the assistive technology was not compatible with the browser at the moment of testing (e.g. Jaws+Edge, this may change in the future) unknown | We were unable to access, download, install or use the web browser

Other tested screen readers

This list will contain some of the assistive technologies that are still being updated and used, but have only marginal market shares. The list is not exhaustive since some of these solutions are pricey and testing with assistive technologies takes a lot of time since it has to be done by hand.

  | Chrome | Firefox | Opera | Safari | Edge | IE -------|--------|---------|-------|--------|------|--- Microsoft Narrator | n/a | good | n/a | n/a | great | great