1

I have the following styling setup to apply an icon to external links, but I'm having an issue where it's applying to images that are a child of the anchor tag, which I do not want.

a:not(.btn) {
  &[target="_blank"] {
    &:after {
       // The styles I want to apply
    }
  }
}

I've attempted to use the following img:not(:first-child) selector to wrap the block, but it does not seem to do what I want it to.

a:not(.btn) {
  &[target="_blank"] + img:not(:first-child) {
    &:after {
       // The styles I want to apply
    }
  }
}

What is the correct way to adjust this code where it will correctly apply to any anchor tags with target="_blank" but not to those when an img tag is a child.

James Ives
  • 3,040
  • 2
  • 23
  • 46

2 Answers2

1

If you are happy to add a dash of javascript, you can achieve the effect you're after relatively straightforwardly by:

  • adding a class to all anchor elements with target="_blank"
  • removing the same class (the one you just added) from all parent nodes of image elements

Working Example:

// GET ALL THE ANCHORS WITH target="_blank"
const anchorTargetBlanks = [...document.querySelectorAll('[target="_blank"]')];

// ADD A CLASS TO ALL SUCH ANCHORS
anchorTargetBlanks.forEach(anchor => anchor.classList.add('link-contains-no-image'));

// REMOVE THAT CLASS FROM THE PARENT NODE OF EACH IMAGE
[...document.images].forEach((image) => {
  
  if (image.parentNode.getAttribute('target') === '_blank') {
    image.parentNode.classList.remove('link-contains-no-image');
  }

});
ul {
  padding-left: 0;
}

li {
  margin: 1px;
}

img {
  display: inline-block;
  width: 30px;
  height: 30px;
  margin-right: 6px;
  background-color: rgb(0, 0, 191);
  vertical-align: middle;
}

.link-contains-no-image {
  display: block;
  padding: 6px;
  color: rgb(255, 255, 255);
  background-color: rgb(255, 0, 0);
}
<ul>
<li><a href="https://example.com/" target="_blank">Link 1</a></li>
<li><a href="https://example.com/" target="_blank"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'/%3E" alt="Image for Link 2" />Link 2</a></li>
<li><a href="https://example.com/" target="_blank">Link 3</a></li>
<li><a href="https://example.com/" target="_blank">Link 4</a></li>
<li><a href="https://example.com/" target="_blank"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'/%3E" alt="Image for Link 5" />Link 5</a></li>
<li><a href="https://example.com/" target="_blank">Link 6</a></li>
</ul>
Rounin
  • 21,349
  • 4
  • 53
  • 69
0

What you are trying to do is target a parent based on its child, and that is not possible with CSS. You need to use JS or JQuery. Check these answers for more detailed suggestions.

Set parent style via child or Is there a CSS parent selector?

AlenM92
  • 43
  • 4