Search code examples
ioscss-selectorssafari-content-blocker

How to select adjacent content in CSS for a content blocker?


I'm trying to block some content on a page in iOS, and in the HTML below I'm successfully blocking the <img> element because it has an alt attribute with the text in it that I want to block ("football"). I need to also block the link in the <div> that's adjacent to it inside the <li>. Ideally, I'd like to block the entire <li>.

Here's my rule:

[
  {
    "action": {
      "type": "css-display-none",
      "selector": "img[alt*='football']"
    },
    "trigger": {
      "url-filter": ".*"
    }
  }
]

And here's an example of the HTML. Everywhere it says random the class is entirely random so cannot be relied upon or used for blocking as it changes on every page load.

<li class="random-ListItem random">
    <div type="article" class="random-Promo random">
        <div class="random-PromoSwitchLayoutAtBreakpoints random">
            <div class="random-PromoContent random">
                <div spacing="2" class="random-Stack random">
                    <h3>
                        <a href="/articles/whatever" class="random-PromoLink random">
                            <span role="text">
                                <p class="random-PromoHeadline random">
                                    <span aria-hidden="false">Football article</span>
                                </p>
                            </span>
                        </a>
                    </h3>
                </div>
                <div spacing="4" class="random-Stack random">...</div>
                <div class="random-PromoImageContainer random">
                    <div class="random-PromoImageContainerInner random">
                        <div class="random-ImageWrapper random">
                            <span class="random-Placeholder random">
                                <span>
                                    <picture>
                                        <source srcset="https://whatever" type="image/webp" sizes="(max-width: 399px) 240px, 480px">
                                        <img alt="Image of a football" sizes="(max-width: 399px) 240px, 480px" src="https://wherever/football.jpg" srcset="https://whatever" width="240" height="135" class="random">  <!-- This is blocked -->
                                    </picture>
                                </span>
                            </span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</li>

AFAIK I can't select an element by its text content (?), so I can't simply block span[text*='football']. I've tried a lot of different things, and it's possible that once the img is blocked any subsequent block rule fails because there's no img that has the div adjacent to it, so I kinda need to figure out how to block the entire li. Any ideas?


Solution

  • If the entire li is what you want to block you could utilise the new has selector:

    li:has(img[alt*='football']) 
    

    This targets all li elements that have a descendant element that satisfies the criteria within the :has(). Which in your case the li with football in an alt attribute of a nested img will target the li in its entirety

    Your new rule:

    [
      {
        "action": {
          "type": "css-display-none",
          "selector": "li:has(img[alt*='football'])"
        },
        "trigger": {
          "url-filter": ".*"
        }
      }
    ]