-->

Add custom CSS to sprites generated with Compass

2019-05-08 16:46发布

问题:

I have this code in my_images.scss file:

$icon-layout:smart;
$icon-sprite-dimensions: true;
@import "icon/*.png";
@include all-icon-sprites;

The output is something like this:

.icon-sprite, .icon-asterisk, .icon-camera, .icon-clock, ... {
  background: url('/../../media/img/icon-s00227a988a.png') no-repeat;
}

.icon-asterisk {
  background-position: -108px -18px;
  height: 18px;
  width: 18px;
}

.icon-camera {
  background-position: -54px -18px;
  height: 18px;
  width: 18px;
}

How can I change the code to include custom CSS in the output. I want to generate this:

.icon-sprite, .icon-asterisk, .icon-camera, .icon-clock, ... 
{
    background: url('/../../media/img/icon-s00227a988a.png') no-repeat;

    /* My custom CSS here */
    display: inline-block;
}

Important

I have a not very good solution for this: Since these are built using @extend you just need to add a selector named .icon-sprite and include the custom styles. Like so:

.icon-sprite {
  display: inline-block;
}

$icon-layout:smart;
$icon-sprite-dimensions: true;
@import "icon/*.png";
@include all-icon-sprites;

Compiles to something like:

.icon-sprite, .icon-asterisk, .icon-camera, .icon-clock, ... {
  display: inline-block;
}

.icon-sprite, .icon-asterisk, .icon-camera, .icon-clock, ... {
  background: url('/../../media/img/icon-s00227a988a.png') no-repeat;
}
...

But it is completely redundant to duplicate the CSS code. I'd like to generate:

.icon-sprite, .icon-asterisk, .icon-camera, .icon-clock, ... {
  background: url('/../../media/img/icon-s00227a988a.png') no-repeat;
  display: inline-block;
}

Is it possible using Compass? Thanks in advance.

回答1:

Your solution is good enough, i would do that the same way. Your CSS will be gzipped, so the difference in size would by like 10 bytes.

It's the readability of your SASS that matters, not the size of your CSS.

But if you really want your CSS to be compact out of perfectionism, it IS possible with Compass! You'll require some monkey-patching.

1) Inside your project folder, create a lib/ subfolder (if you haven't got it already).

2) Download the erb template file into that folder: https://github.com/chriseppstein/compass/blob/stable/lib/compass/sprite_importer/content.erb#L45

3) Add the display: inline-block; line after line 45 of that file (it's highlighted if you follow the link).

4) Now you have to make Compass make use of that template. Create a sprite_importer.rb next to it and add the following code:

require 'erb'
require 'compass/sprite_importer/binding'
module Compass
  class SpriteImporter < Sass::Importers::Base

    # Generates the Sass for this sprite file
    def self.content_for_images(uri, name, skip_overrides = false)
      template_folder = File.expand_path('../', __FILE__)
      content_template_file = File.join(template_folder, 'content.erb')
      content_template = ERB.new(File.read(content_template_file))
      binder = Compass::Sprites::Binding.new(:name => name, :uri => uri, :skip_overrides => skip_overrides, :sprite_names => sprite_names(uri), :files => files(uri))
      content_template.result(binder.get_binding)
    end
  end
end

This is a copy of sprite_importer.rb, modified to use the custom template and reduced to only the necessary part. It is also modified not to raise Ruby warnings about duplicate constants.

5) Now import that file from config.rb:

require './lib/sprite_importer'

6) Run compass clean and recompile your project.

You'll have the display: inline: block; added to all your sprites just like you wanted:

.sexy-sprite, .sexy-accept, .sexy-add, .sexy-anchor, .sexy-application, .sexy-application_add, .sexy-application_cascade, .sexy-application_delete, .sexy-application_double, .sexy-application_edit, .sexy-application_error, .sexy-application_form, .sexy-application_form_add, .sexy-application_form_delete, .sexy-application_form_edit, .sexy-application_form_magnify, .sexy-application_get, .sexy-application_go, .sexy-application_home, .sexy-application_keyasdf, .sexy-application_lightning, .sexy-application_link, .sexy-application_osx, .sexy-application_osx_terminal, .sexy-application_put, .sexy-application_side_boxes, .sexy-application_side_contract, .sexy-application_side_expand, .sexy-application_side_list, .sexy-application_side_tree, .sexy-application_split, .sexy-application_tile_horizontal, .sexy-application_tile_vertical, .sexy-application_view_columns, .sexy-application_view_detail, .sexy-application_view_gallery, .sexy-application_view_icons, .sexy-application_view_list, .sexy-application_view_tile, .sexy-application_xp, .sexy-application_xp_terminal, .sexy-arrow_branch, .sexy-arrow_divide, .sexy-arrow_down, .sexy-arrow_in, .sexy-arrow_inout, .sexy-arrow_join, .sexy-arrow_left, .sexy-arrow_merge, .sexy-arrow_out, .sexy-arrow_redo, .sexy-arrow_refresh, .sexy-arrow_refresh_small, .sexy-arrow_right, .sexy-arrow_rotate_anticlockwise, .sexy-arrow_rotate_clockwise, .sexy-arrow_switch, .sexy-arrow_turn_left, .sexy-arrow_turn_right, .sexy-arrow_undo, .sexy-arrow_up, .sexy-asterisk_orange, .sexy-asterisk_yellow, .sexy-attach {
  background: url('/images/sexy-sce786a2ec5.png') no-repeat;
  display: inline-block;
}

You also may add some logic to the erb template so that inline-block; is only added when necessary.