Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

1.3 : Requiring <base> tags means I can't use SVG with clip-path, mask, etc... #8934

Description

@ryanzec

With the recent change of requiring the <base> tag, now all my SVG icons that I use that have clip-paths, masks, etc... are broken. I can't set the urls for those properties to absolute paths because the url constantly changes when navigate in the app and I can't set relative urls because of the <base> now. The only thing I can do is not use HTML5 mode which I just don't like.

I don't see why the <base> tag should be required when historically from what I read it generally causes more issues than is solves (like this one). As far as linking goes, I can't think of a reason they should not all start with a /. There is no reason I can think of where when on /page1 and you want to link to /page2 you would need to have the link be page2. As far as the deep url issue, have that be something you can configure with $locationProvider or something.

I really hope this change can be un-done or someone can tell me how to use SVG properties that require url() while still being able to HTML5 mode.

Activity

  1. caitp commented on Sep 4, 2014

    @caitp
    Contributor

    or someone can tell me how to use SVG properties that require url() while still being able to HTML5 mode.

    You shold be able to use a full URL (including scheme + host + path) for these --- the browser won't rewrite those relative to the <base> tag.

    As for undoing it, well we tried something else first, but unfortunately the alternative had more problems. I agree that it really sucks that the <base> tag is so coupled with the application base url in angular, but there's little we can do about it without making things even worse :(

  2. caitp commented on Sep 4, 2014

    @caitp
    Contributor

    You could go bug anne van kesteren about it though :p maybe he'll let us have multiple base tags in the future, for different things

  3. added this to the milestone on Sep 4, 2014
  4. caitp commented on Sep 4, 2014

    @caitp
    Contributor
  5. ryanzec commented on Sep 4, 2014

    @ryanzec
    Author

    You should be able to use a full URL (including scheme + host + path) for these --- the browser won't rewrite those relative to the tag.

    I wish it were that easy. When I try that, the SVG icons look fine on initial page load however the first time I navigate to a different page within the application, all the clipping goes away. The clipping only works on the initially loaded page because that is the full path that is used in the SVG. The SVG icons are not getting recompiled or anything like that (using ui-router in order to have certain view that don't change when moving around the application). I assume this is because once I navigate to a new page, the SVG no longer can find the element (since the full url does not match the new url after the initial page load).

  6. caitp commented on Sep 4, 2014

    @caitp
    Contributor

    Yes, that's more of a problem... I'll see if there's anything we can do about that without reverting the location fixes

  7. caitp commented on Sep 4, 2014

    @caitp
    Contributor

    Could you like, provide a reproduction to what you're talking about (wrt to clipping being broken)? I'm not really getting that --- even just showing the markup of your svg would be helpful

  8. ryanzec commented on Sep 4, 2014

    @ryanzec
    Author

    @caitp
    Without <base>:

    http://plnkr.co/edit/ykU211Qgx2HczNnM5LXY?p=preview

    With <base>:

    http://plnkr.co/edit/syDHyECUmo5aJyw7LzwI?p=preview

    The SVG has a mask and is generated with Sketch but I believe most vector software will export similar to this.

  9. caitp commented on Sep 4, 2014

    @caitp
    Contributor

    Thanks --- so yes, changing the mask URI to an absolute url does work around it... could probably write a quick tool to do that for you. I don't think we can really do that in core though ._.

    You can author the SVG differently though, using paths instead of --- it's a bit of a heavier transfer, but it should work for you.

  10. caitp commented on Sep 4, 2014

    @caitp
    Contributor

    I'm not sure we'd be wise to automate changing FuncIRI notation on route change though :(

  11. ryanzec commented on Sep 5, 2014

    @ryanzec
    Author

    Digging into more, it seems like it has to do with the library I am using for SVG icons, Iconic. When I remove the iconic.js library that is being used to load the icons and fallback to the SVGInjector library, route switching no longer effect the icons properties that use url() (though I still need to add the absolute url to the beginning which is not that big of an issue).

    I still hate the fact that 1.3 requires the <base> tag with HTML5 mode. Are there any downsides (besides a slight ugly URL) that I should be aware of when not using HTML5 mode?

  12. tbosch commented on Sep 5, 2014

    @tbosch
    Contributor

    Hi,
    not using html5 mode will not resolve your problem, as Angular then uses the hash fragment for storing the location information within your app, so all links will be relative to the initial url with which the page was loaded as well (same effect as using html5mode with the <base> tag).

    The major problem with html5mode and not having a <base> tag is that you get different behavior on older browsers that don't support the history API (IE9) and newer browsers. Older browsers will fall back to using the hash fragment, which makes all links relative to the initial url.

    The problem with svg attributes that use url is that they don't respect the value of the <base> tag and always uses the current path defined by the history api, in contrast to xlink:href.

    See this plunker: http://plnkr.co/edit/yRChhan8SB5fQIy9BmjC?p=preview
    Note how the <use xlink:href="#path-1"></use> is working correctly, but the mask="url(#mask-2)" is not.

    Also note that changing the path via the history API AFTER the svg has been loaded does not seem a problem!
    Thinking about how to solve this...

  13. tbosch commented on Sep 5, 2014

    @tbosch
    Contributor

    Ah, calling history.pushState right after the <svg> also causes the problem, but calling history.pushState in a setTimeout does not :-(

  14. 45 remaining items

  15. added 2 commits that reference this issue on Sep 23, 2014
    d05957c
    499ebaa
  16. jeffbcross commented on Sep 23, 2014

    @jeffbcross
    Contributor

    I've introduced the ability to remove the base tag requirement in dc3de7f by passing an object to html5Mode() with a property of requireBase set to false:

    $locationProvider.html5Mode({enabled: true, requireBase: false});

    Setting this removes the requirement of having a base tag in the document, with the caveat that IE9 will have issues with resolving relative paths.

  17. ryanzec commented on Oct 9, 2014

    @ryanzec
    Author

    I always use absolute paths anyways (and I might only have to support IE10+) so this should work for me.

  18. ivanzotov commented on Mar 2, 2015

    @ivanzotov

    @jeffbcross, thanks! $locationProvider.html5Mode({enabled: true, requireBase: false} works for me

  19. chedched commented on Aug 11, 2015

    @chedched

    @jeffbcross Thanks a lot for this!

  20. symis84 commented on Dec 9, 2015

    @symis84

    screen shot 2015-12-09 at 12 31 47

  21. kuroky360 commented on Jun 28, 2016

    @kuroky360
    Contributor

    Thanks.

  22. bradwbradw commented on Dec 6, 2016

    @bradwbradw

    This may be useful for anyone running into this who still wants to have a <base> tag

    // in controller:
    $scope.absoluteRef = function (id) {
              return 'url(' + $location.absUrl() + '#' + id + ')';
            }
    

    in template (example):

    <svg xmlns="http://www.w3.org/2000/svg">
    
          <radialGradient id="my-radial-gradient">
            <stop offset="15%" stop-color="white"></stop>
            ...
          </radialGradient>
    
          <circle fill="{{absoluteRef('my-radial-gradient')}}">
          </circle>
    </svg>
    
    
    

    I don't know if there's anything about 'fill' that means this won't work with 'mask' or 'clip-path', but $location.absUrl() will provide the current URL for any dynamically changing url, and it works for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions