Prevent extlink icons from breaking into new lines

Created on 22 September 2020, about 4 years ago
Updated 5 September 2024, 2 months ago

Problem/Motivation

Let's say we have a fixed div with some long text inside that just fits the div's width. Because icons are appended/prepended with a span element, they break into a new line, which looks bad imho. See the screenshot attached.

Steps to reproduce

Have a div with fixed width with a long link external inside.

Proposed resolution

Add a new setting to attach the ext icon as before/after element. This would force the link to be a block element and stick together.

📌 Task
Status

Fixed

Version

2.0

Component

Code

Created by

🇸🇮Slovenia sasanikolic

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇺🇸United States itmaybejj

    Here's another approach altogether → .

    If the module is set to append, it looks for the last text node in the link, wraps it in a span, and inserts the image or FA class into the span rather than the parent link. The span's class prevents wrapping.

    From:

    <a href class="ext">Link Text <svg class="ext">...</svg></a>
    

    to:

    <a href class="ext">Link <span class="extlink-nobreak">Text <svg class="ext">...</svg></span></a>
    
  • Status changed to Needs review about 1 year ago
  • 🇺🇸United States itmaybejj
  • Status changed to Needs work about 1 year ago
  • 🇷🇸Serbia pivica

    Quick update based on original issue description and old comments from @sasanikolic.

    Internally we figured out that the main problem we have is with FA CSS default rule

    .fa {
      display: inline-block;
    }
    

    This rule will break icon to the next line as a single word if there is not enough room. In our base custom theme we will just add CSS override for this like

    .span.extlink .fa {
      display: inline;
    }
    

    and this simple fix is enough to improve icon line wrapping behaviour - now if there is not enough space the icon will wrap together with last word which looks much better.

    We need to test this a bit more in custom projects, but it seems it is working great for now. Based on this I would recommend we drop very complex JS change approach for fixing this in previous patch and then just close this issue or maybe consider adding some similar rule in extlink CSS.

  • 🇺🇸United States bkosborne New Jersey, USA

    Using font-awesome icons is an optional feature - we're using SVGs

  • 🇷🇸Serbia pivica

    > Using font-awesome icons is an optional feature - we're using SVGs

    The original issue and patches from @sasanikolic targeted Font Awesome case and not SVG inline images.

    Not sure about the approach in comment 11 didn't checked/tested that one.

    Quickly checked locally using of SVG images instead of FA icons. For me there were two problems for mailto icon:

    1. Provided SVG image form mailto had buggy default viewBox definition of `viewBox="0 10 70 20"`. Even without looking into browser this aspect ratio of 70 to 10 just sounds very wrong. Changing that to something like `viewBox="0 0 60 60"` is giving much better result.

    This SVG definition is acutally coming also from JS extlink.js file:

    if (class_name === drupalSettings.data.extlink.mailtoClass) {
              $link[icon_placement]('<svg focusable="false" class="' + class_name + '" role="img" aria-label="' + drupalSettings.data.extlink.mailtoLabel + '" xmlns="http://www.w3.org/2000/svg" viewBox="0 10 70 20"><metadata><sfw xmlns="http://ns.adobe.com/SaveForWeb/1.0/"><sliceSourceBounds y="-8160" x="-8165" width="16389" height="16384" bottomLeftOrigin="true"/><optimizationSettings><targetSettings targetSettingsID="0" fileFormat="PNG24Format"><PNG24Format transparency="true" filtered="false" interlaced="false" noMatteColor="false" matteColor="#FFFFFF"/></targetSettings></optimizationSettings></sfw></metadata><title>' + drupalSettings.data.extlink.mailtoLabel + '</title><path d="M56 14H8c-1.1 0-2 0.9-2 2v32c0 1.1 0.9 2 2 2h48c1.1 0 2-0.9 2-2V16C58 14.9 57.1 14 56 14zM50.5 18L32 33.4 13.5 18H50.5zM10 46V20.3l20.7 17.3C31.1 37.8 31.5 38 32 38s0.9-0.2 1.3-0.5L54 20.3V46H10z"/></svg>');
    }
    

    Beside wrong viewBox definition there is a lot of weird stuff going on in this SVG and this should be optimized much better like probably removing metadata tag and everything inside of it. Same goes for ext SVG image definition - it needs cleanup and check of viewBox definition.

    2. Then I just needed to add next CSS rule to make stuff look OK:

    svg.mailto {
      height: 1em;
    }
    

    Depending what look you want you would probably want to add some spacing between text and svg icon horizontally, but that also depends on your design. Anyway this looks good enough and more importantly wrapping works in the same way as for FA case with display inline.

    Based on this I still think this should be fixed just with simple CSS changes and not with adding more JS code and complexity in that layer.

  • 🇺🇸United States itmaybejj

    I think the SVG icons need the JS approach in #11.

    But if display:inline did work for FontAwesome, the extra JS could be set to only fire when the module config is set to SVG.

  • 🇷🇸Serbia pivica

    I just found out that there is `text-wrap: balance` CSS option which works great in improving text wrapping of element, including any icon it has.

    It is still not supported in Safari but it is in TP for desktop version. Check more on https://caniuse.com/css-text-wrap-balance.

  • 🇺🇸United States smustgrave
  • 🇺🇸United States smustgrave

    Curious instead of a js solution if prepend/append can be done with just css and if after/before gets a wrapper around the link and icon?

  • First commit to issue fork.
  • 🇪🇸Spain vidorado Pamplona (Navarra)

    I'm not 100% sure, but a purely CSS solution would require using Unicode characters in the content CSS attribute of the ::after and ::before pseudo-elements.

    Regarding your question about the "wrapper around the link and icon": if I understand correctly, you are asking whether a wrapper is being used or not, correct? I have conducted some tests and found that it is not. The icon is simply placed before the <a> element.

    Nevermind, I've tested the solution in #11 and it works well for me, even though I have tricky CSS in my anchor, with a span inside that has a display: block. So I've added it to the MR.

  • Status changed to Fixed 4 months ago
  • 🇺🇸United States smustgrave

    Will include with next release of 2.0.x

  • Automatically closed - issue fixed for 2 weeks with no activity.

  • 🇨🇦Canada arakwar

    While I can understand the logic behind this, I have to point out that it can break existing themes... Having no way of turning that new behavior off is an issue.

  • Echoing #27's concern here.
    The intentions of this change are fine for "normal links" that contain multiple words.

    But maybe no thought was put into 'mailto:' links, where there is typically no natural word breaks in the link's text.
    For example: firstname.lastname@longdomainnamehere.com

    Our sites had CSS that forced email-address links to wrap if necessary. Extlink's new "extlink-nobreak" markup and CSS overrides that now, and in narrow spaces - like sidebars or cards in a grid-layout - we get a broken layout (horizon overflow, scrollbars) or text that gets cutoff (in cases where the parent container has `overflow: hidden`).

    The CSS we were using to ensure long email address links did not break horizontal flow.
    a[href^="mailto"] { overflow-wrap: break-word; }

    ---

    Our temporary workaround is to completely disable Extlink's processing of 'mailto:' links in the module's options.

  • 🇺🇸United States smustgrave

    Would recommend a new ticket to address future enhancements of the feature.

Production build 0.71.5 2024