Yii 1.1: Provide SVG when the browser supports it, else PNG (using CHtml::image overload)

2 followers

Modern browsers support SVG, older browsers do not. This replacement for CHtml::image() allows you to handle to propose SVG in an efficient way with PNG as a fallback.

On the first load, it will wrap images in a structure that holds both the SVG and PNG alternative. In that case it is the browser that "selects" the right image. During that load, the browser will also set a cookie indicating that it supports SVG as an image or not.

On the second load, or for subsequent ajax loads, the cookie will tell if the browser supports SVG for images. So instead of rendering a complex structure, either the SVG is rendered or the PNG is rendered. This is more efficient.

So basically, you have to use this 'image()' method, which is proposed here in a class overloading 'CHtml'. Then whenever you give an image with a '.svg' extension, you need to provide the 'png' alternative in the same location.

class YHtml extends CHtml {
    private static $svgAsImg;
    private static $jsSvgAsImg=false;
    /**
     * Generates an image tag.
         * 
         * If the image is 'svg', checks the browser compatibility (cookie)
         * and adds 'png' fallback if the browser is not known to support 'svg'.
     *
     * @param string $src the image URL
     * @param string $alt the alternative text display
     * @param array $htmlOptions additional HTML attributes (see {@link tag}).
resizing.
     * @return string the generated image tag
     */
    public static function image($src,$alt='',$htmlOptions=array())
    {
        if(!isset(self::$svgAsImg)) {
            if(isset($_COOKIE['svgasimg'])) { // Can't use cookie manager,
                                              // this is an unsafe cookie
                self::$svgAsImg=($_COOKIE['svgasimg'] === 'true');
            } else {
                self::$svgAsImg=null;
            }
        }
        if(self::$svgAsImg===null && !self::$jsSvgAsImg) {
            Yii::app()->clientScript
                ->registerCoreScript('jquery')
                ->registerCoreScript('cookie')
                ->registerScript('svgasimg', 
                    'jQuery.cookie("svgasimg",document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", "1.1"));');
            self::$jsSvgAsImg=true;
        }
 
        if(substr($src,-4)==='.svg') {
            if(!self::$svgAsImg) {
                // svg file, add alternative for browsers that do not support SVG.
                // See http://coding.smashingmagazine.com/2013/06/02/clown-car-technique-solving-for-adaptive-images-in-responsive-web-design/
                $imgHtmlOptions=$htmlOptions;
                //Next line is ok when method for converting svg on server side.
                //$imgHtmlOptions['src']=Yii::app()->createUrl('image/png',array('src'=>$src));
                $imgHtmlOptions['src']=substr($src,0,strlen($src)-4).'.png';
                $imgHtmlOptions['alt']=$alt;
 
                $img="<!--[if lte IE 8]>".self::tag('img',$imgHtmlOptions)."<![endif]-->";
                $htmlOptions['data']=$src;
                //$htmlOptions['alt']=$alt;
                $htmlOptions['type']='image/svg+xml';
                if(self::$svgAsImg===null) {
                    return self::tag('object',$htmlOptions,$img);
                } else {
                    return self::tag('img',$imgHtmlOptions);
                }
            } else {
                $htmlOptions['src']=$src;
                $htmlOptions['alt']=$alt;
                return self::tag('img',$htmlOptions);
            }
        }
        $htmlOptions['src']=$src;
        $htmlOptions['alt']=$alt;
        return self::tag('img',$htmlOptions);
    }

Be the first person to leave a comment

Please to leave your comment.

Write new article
  • Written by: le_top
  • Category: Tips
  • Yii Version: 1.1
  • Votes: +1 / -1
  • Viewed: 4,592 times
  • Created on: Oct 31, 2014
  • Last updated: Nov 1, 2014
  • Tags: svg, CHtml::image, images