SO-21094865

by David Thomas

HTML

<form action="#" method="post">
  <fieldset>
    <legend>Does your browser support..?</legend>
    <label>
      <span>Enter a selector to test</span>
      <input type="text" id="testSelector">
    </label>
    <button type="button">Check your browser</button>
  </fieldset>
  <ul id="results"></ul>
</form>

CSS

*, ::before,::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

form {
  margin-block: 1em;
  margin-inline: auto;
  width: clamp(30rem, 60vw, 1000px);
}

fieldset {
  display: grid;
  gap: 1em;
  grid-auto-rows: min-content;
  grid-template-columns: repeat(4, 1fr);
  padding-block: 0.25em;
  padding-inline: 0.5em;
}

label {
  display: flex;
  flex-flow: row nowrap;
  gap: 1em;
  grid-column: 1 / -1;
  margin-block: 1em;
  margin-inline: 0.5em;
  padding: 0.25em;
}

label span {
  align-self: center;
}

label span::after {
  content: ': ';
}

label input {
  flex-grow: 1;
  object-fit: cover;
  padding: 0.25em;
}

button {
  grid-column: -2 / span 2;
}

#results li {
  border-block-end-width: 3px;
  border-block-end-style: solid;
  font-family: monospace;
  font-size: 1.5em;
  padding-block: 0.25em;
  padding-inline: 0.5em;
}

.supported {
  border-block-end-color: lime;
}

.supported::marker {
  content: '\2713';
}

.unsupported {
  border-block-end-color: red;
}

.unsupported::marker {
  content: '\2717';
}

JavaScript

// some DOM utilities and helpers,
// caching document as I don't enjoy typing that much:
const D = document,
	// aliasing document.querySelector() and element.querySelector()
  // again, because I don't enjoy typing; here the function takes
  // two arguments 'sel' and 'context',
  // 'sel' is a String, and is the selector for the element we're
  // trying to retrieve;
  // 'context' is the element/node we wish to search within; if
  // no context is passed we default to document.querySelector()
  // otherwise we use Element.querySelector():
  get = (sel, context = D) => context.querySelector(sel),
  // as above, except it's an alias for querySelectorAll(), and
  // here we return an Array of nodes instead of a NodeList in
  // order to use Array methods when/if required:
  getAll = (sel, context = D) => [...context.querySelectorAll(sel)],
  // alias for document.createElement(), which also allows properties
  // to be set on the created element:
  create = (tag, prop) => document.createElement(tag),
  // simple function to allow for more elaborate templates, and
  // arguments if required later:
  templatedResult = (text) => `<code>${text}</code>`,
  // named function to assess whether the browser supports/implements
  // a given selector; this takes a reference to the Event Object
  // passed automatically from EventTarget.addEventListener():
  verifySelectorCompatibility = (evt) => {
  	// preventing default actions (as one of the events to which
    // bind the function is form.submit):
  	evt.preventDefault();
    
    // gathering variables/data
    // here we retrieve the first/only <input> element within
    // the document::
    const input = get('#testSelector'),
    	// we retrieve the value from the <input> and trim that
      // value of it's leading/trailing white-space:
      selector = input.value.trim(),
      // we retrieve the element with id=results:
      output = get('#results'),
      // we use the CSS.supports() function to assess...