Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't render CSS in defs mode #45

Closed
antonkai2k opened this issue Jan 24, 2015 · 22 comments
Closed

Can't render CSS in defs mode #45

antonkai2k opened this issue Jan 24, 2015 · 22 comments
Assignees

Comments

@antonkai2k
Copy link

Is it really impossible to render css/stylus/etc in defs mode? Need this for full control with CSS, e.g. adaptive sizing.
I did read all docs and I see this possible only in css/view modes.

@jkphl
Copy link
Collaborator

jkphl commented Jan 24, 2015

Hi @lookfortheroot,

this is a duplicate of grunt-svg-sprite issue #31. As it happens, I'm just about adding the possibility to render a CSS (et al.) with the shape dimensions. What else would you need?

Cheers,
Joschi

@jkphl jkphl self-assigned this Jan 24, 2015
@antonkai2k
Copy link
Author

Same render possibilities like in css/view modes would be nice.
Thanks a lot for your work, I'll be wait :)

@jkphl
Copy link
Collaborator

jkphl commented Jan 24, 2015

Well, the very same don't make any sense (and are impossible, by the way). By definition, a defs sprite is not usable as a CSS sprite (i.e. for background images), as the shapes are not positioned in any way within the sprite. The sprite just serves as a "shape library" and you may <use> the contained shapes as foreground images (the same applies for the symbol and stack sprites by the way). The dimension properties are the only ones I can think of that would be useful. Right?

@antonkai2k
Copy link
Author

Well, this is right.
I use another approach - inject SVG by AJAX for caching, and move shapes to placeholders for full CSS/animation/transform/etc control. So just now all I need is sizes in separate Stylus/CSS file.

@jkphl
Copy link
Collaborator

jkphl commented Jan 24, 2015

Thou shalt get that. ;)

I might delay the next release until Monday, however, as I'd like to wait for the upcoming lodash release.

By the way, that SVG injection approach you are talking about will most likely be featured in one of my next iconizr releases, then including support for PNG fallbacks as well. I might consider backporting the SVG part into svg-sprite as well.

@jkphl
Copy link
Collaborator

jkphl commented Jan 24, 2015

Should work now, although still undocumented. Just use it as you would do with css or view mode. A reworked documentation will come soon, as does an official release. ;)

Cheers,
Joschi

@jkphl jkphl closed this as completed Jan 24, 2015
@antonkai2k
Copy link
Author

Yay, this was fast. Thanks a lot 👍

@jkphl
Copy link
Collaborator

jkphl commented Jan 24, 2015

You're welcome. As I said, I was just about it anyway. Didn't spend too much time testing though — would be nice if you could give me some feedback if this works for you. :)

@antonkai2k
Copy link
Author

It almost works ;)

  1. In generated css/stylus/etc there is a space instead a dot:
[space]icon-logo
    width 10px
    height 10px
  1. We need then to eliminate width and height attributes in resulting spritesheet for svg+css sizes or it won't work.
    And they somehow appending even if they were not in the SVG source. I don't see how to remove it in config :(

  2. Besides, it seems SVGO transforms doesn't work. Is it only for me? No errors, nothing:

mode: {...},
transform : [
    {svgo:  {
        plugins: [
            {cleanupIDs: true},
            {cleanupEnableBackground: true}
        ]
    }}
]

@jkphl
Copy link
Collaborator

jkphl commented Jan 24, 2015

  1. In generated css/stylus/etc there is a space instead a dot:

No, it's not. I double checked it with different output modes and all the stylesheet resource types. I get a dot, always. Any chance there's another problem on your side? Did you alter the prefix or the dimensions option? What are your values? Any other possibility?

  1. We need then to eliminate width and height attributes in resulting spritesheet for svg+css sizes or it won't work. And they somehow appending even if they were not in the SVG source. I don't see how to remove it in config :(

I'm not sure if I completely understand your problem. In case you set the inline option to true, the sprite gets prepared for being embedded into an HTML document. For this purpose, width="0" height="0" style="position:absolute" is added to the root SVG element so that the sprite doesn't get rendered visually. This should not affect the regular usefulness of the sprite, however. Please check the example document for reference (enabled by example: true). Regarding your SVG injection approach, I have no idea whether the defs sprite is suited for that. Withouth having tried, I doubt it somehow ...

  1. Besides, it seems SVGO transforms doesn't work. Is it only for me? No errors, nothing:

By default, almost every SVGO plugin is enabled. These are the defaults:

defaultPluginConfig                 = [
//  {cleanupAttrs                   : true}, // cleanup attributes from newlines, trailing and repeating spaces
//  {removeDoctype                  : true}, // remove doctype declaration
//  {removeXMLProcInst              : true}, // remove XML processing instructions
//  {removeComments                 : true}, // remove comments
//  {removeMetadata                 : true}, // remove `<metadata>`
//  {removeTitle                    : true}, // remove `<title>`
//  {removeEditorsNSData            : true}, // remove editors namespaces, elements and attributes
//  {removeEmptyAttrs               : true}, // remove empty attributes
//  {removeHiddenElems              : true}, // remove hidden elements
//  {removeEmptyText                : true}, // remove empty Text elements
//  {removeEmptyContainers          : true}, // remove empty Container elements
//  {removeViewBox                  : true}, // remove `viewBox` attribute when possible
//  {cleanupEnableBackground        : true}, // remove or cleanup `enable-background` attribute when possible
//  {convertStyleToAttrs            : true}, // convert styles into attributes
//  {convertColors                  : true}, // convert colors (from `rgb()` to `#rrggbb`, from `#rrggbb` to `#rgb`)
//  {convertPathData                : true}, // convert Path data to relative, convert one segment to another, trim useless delimiters and much more
//  {convertTransform               : true}, // collapse multiple transforms into one, convert matrices to the short aliases and much more
//  {removeUnknownsAndDefaults      : true}, // remove unknown elements content and attributes, remove attrs with default values
//  {removeNonInheritableGroupAttrs : true}, // remove non-inheritable group's "presentation" attributes
//  {removeUnusedNS                 : true}, // remove unused namespaces declaration
//  {cleanupIDs                     : true}, // remove unused and minify used IDs
//  {cleanupNumericValues           : true}, // round numeric values to the fixed precision, remove default 'px' units
//  {moveElemsAttrsToGroup          : true}, // move elements attributes to the existing group wrapper
    {moveGroupAttrsToElems          : false} // move some group attributes to the content elements
//  {collapseGroups                 : true}, // collapse useless groups
//  {removeRasterImages             : false}, // remove raster images (disabled by default)
//  {mergePaths                     : true}, // merge multiple Paths into one
//  {convertShapeToPath             : true}, // convert some basic shapes to path
//  {transformsWithOnePath          : true}, // apply transforms, crop by real width, center vertical alignment and resize SVG with one Path inside
],

Only the moveGroupAttrsToElems plugin gets disabled as it's too aggressive in most of the cases. For me, SVGO seems to work fine (and noone else complained so far), so I guess there must be another problem on your end. Possible? Can you run SVGO from the command line or from another module? Can you isolate the problem?

@antonkai2k
Copy link
Author

<svg width="0" height="0" style="position:absolute">
    <defs>
        <svg width="10" height="10" id="icon-logo">...</svg> //These attrs blocks CSS sizing, e.g. in %
    </defs>
</svg>

@jkphl
Copy link
Collaborator

jkphl commented Jan 25, 2015

I'm sorry, but I think that what you're trying to achieve is something that is specific to your SVG injection approach — which is not what the defs sprite is made for. Once again, please have a look at the example document to see how the sprite is intended to be used. The <use>ing SVG element may well be styled via CSS:

<svg viewBox="0 0 68 68" class="my-custom-css-class-with-relative-dimensions">
    <use xlink:href="#icon-logo"/>
</shapes>

@antonkai2k
Copy link
Author

Of course, this is one of the best methods.
But :hover and other effects still buggy with <use> even in latest Chrome. Only truly inline SVG works cross-browser.

That is why I try combine best parts:

  • AJAX injecting - cache advantage
  • Moving shapes in their placeholders by tiny JS - inline SVG advantage
  • Sizes generated in CSS, not SVG - responsive design advantage

So using defs fastest in DOM - just moving AJAX'ed <svg> shapes without any tags converting like <g> or <symbol>.
And last stuck for me is impossibility to get rid 'width' and 'height' attributes ;)

@jkphl
Copy link
Collaborator

jkphl commented Jan 26, 2015

I'm still thinking about removing the widthandheightattributes of the inner` elements. Gonna reopen this issue so that I don't forget it ...

@jkphl
Copy link
Collaborator

jkphl commented Jan 28, 2015

As of release v1.0.13 you can control whether you want to have width and height attributes. Please have a look at the svg.dimensionAttributes and shape.dimension.attributes options and also let me know if this works for you now. Thanks! :)

@jkphl jkphl closed this as completed Jan 28, 2015
@antonkai2k
Copy link
Author

It works. Thanks!

@antonkai2k
Copy link
Author

But I have last question.
For final cross-browser responsitivity it's need a little trick, here is a pseudo-code:
padding-top: (svg.height / svg.width)%

I don't understand, how in Gulp to pass calculated value to template? I always get errors:

variables: {
    'ptop': function(sprite, render) {
        sprite.height.inner / sprite.width.inner //no one object exists
    }
}

@jkphl
Copy link
Collaborator

jkphl commented Jan 29, 2015

Please refer to the Mustache documentation to learn about the usage of callbacks (which seems, in general, a legit solution for your problem). AFAIK you may only pass strings to these functions, and you won't be able to pass the sprite object variable with all its properties. I guess you will have to pass the height and width as a string (delimited with a separator) and split it again inside your function before processing.

@antonkai2k
Copy link
Author

I meant I can't find right object for calculates.
In your docs there is only one example, and I trying:

{
    variables: {
        padtop: function(sprite, render) {
              sprite //'undefined'
              sprite.spriteWidth //'undefined'
        }
    }
}
{
    variables: {
        padtop: function() {
            return function(sprite, render) {
                sprite //'undefined'
                sprite.spriteWidth //'undefined'
            }
        }
    }
}

Etc etc. I don't understand how to do it.

@jkphl
Copy link
Collaborator

jkphl commented Jan 29, 2015

Please read my previous comment. You cannot pass in objects to Mustache functions, only strings. In the template you need to use something like:

{{#padtop}}width|height{{/padtop}}

and then in function:

padtop: function() {
    return function(dimensions, render) {
        dimensions = dimensions.split('|');
        /* ... */
    }
}

@antonkai2k
Copy link
Author

Sorry for my English, it seems I poorly explained and you misunderstood me :)
In Gulp I want to precalculate (svg.height / svg.width) and pass a result in the template.
So I don't know how to get width and height of the processed svg:

.pipe(svgSprite({
    mode: {...},
    variables: {
        my_result: {
            return (svg.height / svg.width)
        }
    }
})

And in the template something like: padding-top {{my_result}}
Is it possible? Any help will be appreciated.
Thanks!

@jkphl
Copy link
Collaborator

jkphl commented Feb 2, 2015

Please re-read my comment above — most of the answer to your problem stands written there. The variables available in each template are documented here. You will want to go for width.outer an height.outer I guess. Pass these into an appropriately written callback function and do you pre-calculation.

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

No branches or pull requests

2 participants