Skip to content

Instantly share code, notes, and snippets.

@PaulGuo
Created November 24, 2011 09:24
Show Gist options
  • Save PaulGuo/1390952 to your computer and use it in GitHub Desktop.
Save PaulGuo/1390952 to your computer and use it in GitHub Desktop.
Auto CSS Sprites
#!/usr/bin/env python
import os
import os.path as p
import Image
css_inline_item_template='''
%(selector)s {
background: url(%(url)s) no-repeat -%(xpos)spx -%(ypos)spx;
width:%(width)spx;
height:%(height)spx;
}
'''
css_base_template='''
%(base_selector)s {
background-image:url(%(url)s);
background-repeat:no-repeat;
}
'''
css_base_item_template='''
%(selector)s {
background-position:-%(xpos)spx -%(ypos)spx;
width:%(width)spx;
height:%(height)spx;
}
'''
def generate_sprite(images,margin=10,align='left'):
def _basename(path):
return p.splitext(p.basename(path))[0]
data=[]
master_width=max(*[i.size[0] for i in images])
master_height=sum([i.size[1] for i in images])+margin*(len(images)-1)
sprite=Image.new(
mode='RGBA',
size=(master_width,master_height),
color=(0,0,0,0)) # fully transparent
location=0
for image in images:
# if 'transparency' in image.info:
# print('Warning: Incorrect transparency mode: '+image.filename)
xpos=0 if(align=='left') else master_width-image.size[0]
sprite.paste(image,(xpos,location))
data.append({
'xpos':xpos,
'ypos':location,
'dir':_basename(p.dirname(image.filename)),
'file':_basename(image.filename),
'width':image.size[0],
'height':image.size[1],
})
location+=image.size[1]+margin
return sprite,data
def render_css(base_template,item_template,css_data,sprite_url,base_selector,selector):
base_info={
'base_selector':base_selector,
'url':sprite_url,
}
base_css=base_template % base_info
items_css='\n'.join([
item_template % dict([('selector',selector % image_data)]
+image_data.items()
+base_info.items())
for image_data in css_data])
return base_css+items_css
def create_sprite_and_css(images_dir,css_output,sprite_output,selector='.%(file)s',base_selector='.sprite',url=None,inline=False,align='left',margin=10):
images=[Image.open(p.join(images_dir,filename))
for filename in os.listdir(images_dir)
if not filename.startswith('.')]
sprite,css_data=generate_sprite(images,margin=margin,align=align)
# TODO
# convert png24 to png8 hack for ie6
# sprite=sprite.convert('RGB').convert('P',palette=Image.ADAPTIVE)
# sprite.save(sprite_output,transparency=255)
sprite.save(sprite_output)
sprite_url=url or p.basename(sprite_output)
if inline:
css=render_css('',css_inline_item_template,css_data,sprite_url,base_selector,selector)
else:
css=render_css(css_base_template,css_base_item_template,css_data,sprite_url,base_selector,selector)
css_file=open(css_output,'w')
css_file.write(css)
css_file.close()
if __name__=='__main__':
from optparse import OptionParser
usage='usage: %prog [options] images_dir css_output sprite_output'
parser=OptionParser(usage=usage)
parser.add_option('-i','--inline',action='store_true',dest='inline',default=False,help='When set, image url will be put in css rule for every item.')
parser.add_option('-s','--selector',dest='selector',default='.%(file)s',help='Selector template. You can use dir, file, width, height here.')
parser.add_option('-S','--base-selector',dest='base_selector',default='.sprite',help='Base selector template for base css rule (when -i is not set).')
parser.add_option('-u','--url',dest='url',default='',help='Css rule Image url template.')
parser.add_option('-a','--align',dest='align',default='left',help='Css sprites Image align.')
parser.add_option('-m','--margin',dest='margin',default='10',help='Css sprites Image margin.')
(options,args)=parser.parse_args()
if len(args)<3:
print('You must provide all 3 arguments.')
else:
images_dir,css_output,sprite_output=[p.realpath(arg) for arg in args]
create_sprite_and_css(images_dir,css_output,sprite_output,
selector=options.selector,
base_selector=options.base_selector,
inline=options.inline,
url=options.url,
align=options.align,
margin=eval(options.margin))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment