0

We use css to add icons to links to files such as PDFs, Word, Images, etc. For example:

<a href="mypdf.pdf">Download PDF</a>

a[href$=".pdf"]::after {
    content: "\00a0\f1c1";
    display: inline;
    font-family: FontAwesome;
    font-size: 1em;
}

How do I tell CSS to not add an icon if the link is around an image?

<a href="mypdf.pdf"><img src="someimage.gif"></a>

I've tried numerous versions of the following with no luck.

a::after img {content: ""}

thanks, Shauna

sfjeld
  • 27
  • 4
  • You can use 'not' attribute in css to avoid image tag and apply on others – Dhara Mar 15 '21 at 22:19
  • Does this answer your question? [Is there a CSS parent selector?](https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector) – mr_joncollette Mar 15 '21 at 22:37
  • Using Javascript, you could query the A tag selectors and then check their children[0] to see if the tagName is an IMG tag, if it is not... create an icon element and add the classList for your ICON then insert the icon element after the a tag element. Depending on how/what your icons are or what determines what icon will be placed behind your a tags, conditionals can be added to check what that logic may be and then add an ICON. – dale landry Mar 15 '21 at 23:04

2 Answers2

0

The css a[href$=".pdf"]::after is targeting extremely wide -- it is literally any <a href="...pdf"> instances. It will add the icon independent of what child elements it contains.

You can add another, more specific, selector such as a.noicon[href$=".pdf"]::after { display: none;} to remove the icon from <a href="mypdf.pdf" class="noicon"><img></a>. You cannot create a selector that targets a child's parent without using Javascript to target it.

It is much wiser to create 'additive' styles that are as specific as you need them such as p a[href$=".pdf"]::after to target all links within paragraphs or .pileoflinks a[href$=".pdf"]::after to target links within a very specific class.

Most ideally, create an instance where someone must make a conscience decision to add the icon: a.download-pdf::after and <a href="[anylink]" class="download-pdf">

mr_joncollette
  • 643
  • 6
  • 9
  • This link https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector will explain a more technical perspective. – mr_joncollette Mar 15 '21 at 22:36
  • Thanks, we have hundreds of links to PDFs and much fewer links to images, so I think we will go with adding a class to the link on images even though not optimal. – sfjeld Mar 16 '21 at 13:01
0

Using Javascript you could do the following:

The following code queries the a tag selectors within a parent element then two helper functions, one that inserts an element after another element, the icon after the iterated a tag value. The other that checks the file extension of a href string helper to identify if the target a tag has an image as its child.

We pass our selectors into a function that loops over the nodeList and checks each iteration for children elements to filter out IMG tags. NOTE: this conditional may need to be changed if you will have child elements directly within the <a> tag that are not <img> tags. Then we extrapolate the file extension from the href string using el.href and pass that into another helper function to get the extension. Create an <i> tag and then use a conditional to check the extension and add the proper icon to the iconClass. Then use icon.classList to add the class (glyphs or other icon types) depending on what you are using. Lastly we add the icon after the a tag element using the helper function insertAfter(icon, tag), pass in the icon and the value of our <a> query => tag.

let el = document.querySelectorAll('#container A')

const insertAfter = (el, referenceNode) => {
  // get parent node of referenceNode then insertBefore el.nextSibling
  referenceNode.parentNode.insertBefore(el, referenceNode.nextSibling);
}
//Helper function from w3c to get extension of path
const getExtension = (path) => {
  let baseName = path.split(/[\\/]/).pop(), // extracts file name from full path
    // (supports separators `\\` and `/`)
    pos = baseName.lastIndexOf("."); // gets the last position of `.`
  if (baseName === "" || pos < 1) // if the file name is empty or ...
    return ""; // the dot not found (-1) or comes first (0)
  return baseName.slice(pos + 1); // extracts extension ignoring "."
}

// function to check element 
const checkImgFunction = (el) => {
  // check all elements in this case we are querying 
  // a tags within the parent element #container
  el.forEach(tag => {
    // condtional to check if the tag does not have children
    // assuming only a tags with textNodes are the targets
    // this conditional may need to change for your needs 
    // if your tag will have `children` that are not images
    // and you wish to include them in your truthy logic
    if (!tag.children[0]) {
      // get the extension type using the helper function getExtension()
      let ext = getExtension(tag.href),
      // create the <i> tag to hold our class glyphcons
      icon = document.createElement('I'),
      // instantiate a class variable that will hold the icon class
      iconClass;
      // conditional to check ext/s
      // one could have an array for this
      // my example is very basic using a if/else consitional
      // could also use switch statements here as well
      if (ext === 'txt') {
        iconClass = "glyphicon glyphicon-paperclip";
      } else if (ext === 'mp3') {
        iconClass = "glyphicon glyphicon-music";
      } else if (ext === 'pdf') {
        iconClass = "glyphicon glyphicon-duplicate";
      } else {
        iconClass = "glyphicon glyphicon-link";
      }
      // now we add the class/s to the icon element
      icon.classList = iconClass;
      // helper function to add the icon AFTER the a tag element...
      insertAfter(icon, tag);
    }
  })
}
// call the function
checkImgFunction(el)
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div id="container">
  <a href="mypdf.pdf"><img src="https://via.placeholder.com/75/0000FF/FFFFFF/?text=Image.com"></a>
  <a href="mypdf.txt"><img src="https://via.placeholder.com/75/0B0B0B/FFFFFF/?text=Image.com"></a>
  <a href="mypdf.txt">Text link </a>
  <a href="mypdf.mp3">MP3 link </a>
  <a href="mypdf.pdf">PDF link </a>
  <a href="mypdf.pdf"><img src="https://via.placeholder.com/75/00FF00/FFFFFF/?text=Image.com"></a>
  <a href="mypdf.pdf"><img src="https://via.placeholder.com/75/FF0000/FFFFFF/?text=Image.com"></a>
  <a href="mypdf.pdf">PDF link </a>
</div>
dale landry
  • 3,942
  • 2
  • 12
  • 22
  • thank you. I'm actually trying to get away from a JavaScript solution, but I appreciate your thoughtful and well documented solution. – sfjeld Mar 16 '21 at 12:59