Avoid the Deprecated :scope Selector

Yesterday while I was optimizing a development project to Internet Explorer, I realized that :scope is a deprecated keyword from all browsers and that it has never been supported by IE.

What is :scope

:scope lets your run a query selector, that takes the current element into the parameter string. For example

node.querySelector(':scope > div')

This would only find div that are direct children to node as I used scope.

Considerations

But since this isn't going to be working in IE I had to come up with another solution. Some solutions suggested prototype hacking to node.find() to make it look similar to jQuery. While I agree sometimes prototyping is okay, however in my opinion that is the case when it's adding new features for old browsers, such as polyfill.io.

The solution

My solution was to create a function, that generates a random ID for the node, if it doesn't have one, and remove it again. Thereby I can still select on it. I created 2 functions one for querySelector and one for querySelectorAll.

To use the function simply call find(document.querySelector('body'), 'div') to find all div that are direct children of body.

    /**
     * Find direct children to node, replicating .querySelector(':scope > [...]')
     */
    function find(node, selector) {
        removeId = false

        if (node.getAttribute('id') === null) {
            node.setAttribute('id', 'ID_' + new Date().getTime())
            removeId = true
        }

        let result = document.querySelector('#' + node.getAttribute('id') + ' > ' + selector)

        if (removeId)
            node.removeAttribute('id')

        return result
    }

    /**
     * Find direct children to node, replicating .querySelectorAll(':scope > [...]')
     */
    function findAll(node, selector) {
        removeId = false

        if (node.getAttribute('id') === null) {
            node.setAttribute('id', 'ID_' + new Date().getTime())
            removeId = true
        }

        let result = document.querySelectorAll('#' + node.getAttribute('id') + ' > ' + selector)

        if (removeId)
            node.removeAttribute('id')

        return result
    }

Expert in Laravel and Vue backed with MySQL databases. Independent developer who does freelance and love to travel. Feel free to drop me a message.

- Emil

Write your comment…

Hi Emil, Thanks for sharing. Looks like :scope is still under consideration for MS Edge as of October 2018 and I can't find any reference that this pseudo-class is deprecated. I see that "scoped" attribute is deprecated but that's very different.

Thank you for you feedback Ogla Sungutay. Do you have a link to your source? Then I will be happy to edit my story.

Reply to this…