Question

UPDATE: My answer now supports automated change of the product base image after swatch. You can also find a more detailed tutorial on how to do this including more images here.

Magento CE 1.9.1.0 comes with a very nice new feature: Configurable Swatches. Unfortunately, this is only available for the RWD package, that comes with the default Magento installation. This is a self answered question on how to make the Magento Configurable Swatches available for the Default package. For anyone who wants to integrate the Configurable Swatches into a custom theme, this info may come in handy as well.

Note 1: This is meant to be an introductional guide on how to make the Configurable Swatches available for Magento's Default package. This could (but may not) work for every custom theme. Always backup your original files (and database) before making any changes.

Note 2: The swatches do work (screen shot below), but I did not yet get the product image to change automatically along with the swatches. I will try and look into this when I find some time.

enter image description here

Feel free to contribute by commenting and make suggestions!

Was it helpful?

Solution

  1. Copy the folder

    app/design/frontend/RWD/default/template/configurableswatches/
    

    and its content to

    app/design/frontend/DEFAULT/default/template/
    

    (or your package template folder)

  2. Copy the file

    app/design/frontend/RWD/default/template/catalog/product/view/type/options/configurable.phtml
    

    to

    app/design/frontend/DEFAULT/default/template/catalog/product/view/type/options/
    

    (or your package template folder)

  3. Copy the file

    app/design/frontend/RWD/default/template/catalog/product/view/media.phtml
    

    to

    app/design/frontend/DEFAULT/default/template/catalog/product/view/
    

    (or your package template folder)

  4. Copy the folders

    skin/frontend/RWD/default/js/configurableswatches/
    skin/frontend/RWD/default/js/lib/
    

    and their content to

    skin/frontend/DEFAULT/default/js/
    

    (or your package skin folder)

  5. Copy the files

    skin/frontend/RWD/default/js/app.js
    skin/frontend/RWD/default/js/minicart.js
    skin/frontend/RWD/default/js/slideshow.js
    

    to

    skin/frontend/DEFAULT/default/js/
    

    (or your package skin folder)

  6. Copy the file

    app/design/frontend/RWD/default/layout/configurableswatches.xml
    

    to

    app/design/frontend/DEFAULT/default/layout/
    

    (or your package layout folder)

  7. Create the file

    app/design/frontend/DEFAULT/default/layout/local.xml
    

If your package layout folder already contains a local.xml file, then do not overwrite it. Have a look at the changes in the next step and copy them to your version of the local.xml file.

  1. Open up local.xml and add the following code:

    <?xml version="1.0"?>
    <layout>
    
        <default>
    
            <reference name="head">
    
                    <action method="addJs"><script>lib/jquery/jquery-1.10.2.min.js</script></action>
                    <action method="addJs"><script>lib/jquery/noconflict.js</script></action>
    
                    <action method="addItem"><type>skin_js</type><name>js/lib/modernizr.custom.min.js</name></action>
                    <action method="addItem"><type>skin_js</type><name>js/lib/selectivizr.js</name></action>
                    <action method="addItem"><type>skin_js</type><name>js/lib/matchMedia.js</name></action>
                    <action method="addItem"><type>skin_js</type><name>js/lib/matchMedia.addListener.js</name></action>
                    <action method="addItem"><type>skin_js</type><name>js/lib/enquire.js</name></action>
                    <action method="addItem"><type>skin_js</type><name>js/app.js</name></action>
                    <action method="addItem"><type>skin_js</type><name>js/lib/jquery.cycle2.min.js</name></action>
                    <action method="addItem"><type>skin_js</type><name>js/lib/jquery.cycle2.swipe.min.js</name></action>
                    <action method="addItem"><type>skin_js</type><name>js/slideshow.js</name></action>
                    <action method="addItem"><type>skin_js</type><name>js/lib/imagesloaded.js</name></action>
            <action method="addItem"><type>skin_js</type><name>js/minicart.js</name></action>
    
            </reference>
    
        </default>
    
        <catalog_product_view>
    
            <reference name="head">
    
                <action method="addItem"><type>skin_js</type><script>js/lib/elevatezoom/jquery.elevateZoom-3.0.8.min.js</script></action>
    
            </reference>
    
            <reference name="product.info.media">
    
                <block type="core/text_list" name="product.info.media.after" as="after" />
    
            </reference>
    
        </catalog_product_view>
    
        <PRODUCT_TYPE_configurable>
    
            <reference name="product.info.options.configurable">
    
                <block type="core/text_list" name="product.info.options.configurable.renderers" as="attr_renderers">
                            <block type="configurableswatches/catalog_product_view_type_configurable_swatches" template="configurableswatches/catalog/product/view/type/options/configurable/swatches.phtml" />
                </block>
                <block type="core/text_list" name="product.info.options.configurable.after" as="after">
                <block type="core/template" template="configurableswatches/catalog/product/view/type/configurable/swatch-js.phtml" />
                </block>
    
            </reference>
    
        </PRODUCT_TYPE_configurable>
    
    </layout>
    
  2. Add the following css to your styles.css file:

    /* ============================================ *
     * Configurable Swatches
     * ============================================ */
    /* Clears */
    .clearfix:after,
    .configurable-swatch-list:after,
    .product-view .product-options .swatch-attr:after {
      content: '';
      display: table;
      clear: both;
    }
    
    /* General Swatch Styling */
    .swatch-link,
    .swatch-label {
      display: block;
      border-radius: 3px;
      font-size: 14px;
      text-align: center;
      color: #636363;
      text-decoration: none;
      box-sizing: content-box;
    }
    
    .swatch-link {
      border: 1px solid #cccccc;
      margin: 0 0 3px;
    }
    .swatch-link img {
      border-radius: 2px;
    }
    .swatch-link:hover {
      cursor: pointer;
      text-decoration: none;
    }
    .swatch-link .x {
      display: none;
      text-indent: -999em;
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      background: url(../images/bg_x.png) center no-repeat transparent;
      z-index: 10;
    }
    .swatch-link.has-image .swatch-label {
      position: relative;
    }
    .swatch-link.has-image img {
      position: absolute;
      top: 0;
      left: 0;
    }
    
    .swatch-label {
      border: 1px solid #fff;
      margin: 0;
      white-space: nowrap;
      background: #f4f4f4;
    }
    
    .configurable-swatch-list {
      margin-left: -3px;
      zoom: 1;
      clear: both;
      -webkit-transform: translateZ(0px);
    }
    .configurable-swatch-list li {
      float: left;
      zoom: 1;
      margin: 0 0 0 3px;
    }
    .products-grid .configurable-swatch-list li {
      display: inline-block;
      float: none;
      margin: 0;
      vertical-align: top;
    }
    .configurable-swatch-list .not-available .x {
      display: block;
    }
    .configurable-swatch-list .not-available .swatch-link {
      border-color: #ededed;
      position: relative;
    }
    .configurable-swatch-list .not-available .swatch-link.has-image img {
      opacity: 0.4;
      filter: alpha(opacity=40);
    }
    .configurable-swatch-list .not-available .swatch-label {
      color: #aaa;
      background: #fff;
    }
    .configurable-swatch-list .wide-swatch .swatch-label {
      padding: 0 6px;
    }
    .configurable-swatch-list .not-available a:focus {
      outline: 0;
    }
    
    #narrow-by-list dd .configurable-swatch-list li {
      margin: 0 0 0 3px;
      width: 47%;
    }
    #narrow-by-list dd .swatch-link {
      border: none;
      line-height: 25px;
      margin-right: 2px;
      text-align: left;
    }
    #narrow-by-list dd .swatch-link.has-image {
      line-height: inherit;
    }
    #narrow-by-list dd .swatch-link:hover .swatch-label {
      border-color: #3399cc;
    }
    #narrow-by-list dd .swatch-label {
      background: #f4f4f4;
      border: 1px solid #cccccc;
      border-radius: 3px;
      display: block;
      float: left;
      line-height: 1.5em;
      margin: 0 5px 0 0;
      padding: 1px 5px;
      white-space: nowrap;
    }
    #narrow-by-list dd .swatch-label img {
      border: 1px solid #fff;
      border-radius: 3px;
      box-sizing: content-box;
    }
    #narrow-by-list dd .has-image .swatch-label {
      padding: 0;
    }
    
    @media only screen and (max-width: 770px) {
      #narrow-by-list dd .configurable-swatch-list li:nth-child(odd) {
        clear: left;
      }
    }
    .currently .swatch-current {
      position: relative;
    }
    .currently .swatch-current .btn-remove {
      margin-top: -10px;
      position: absolute;
      right: 0;
      top: 50%;
    }
    .currently .swatch-current span {
      display: block;
      float: left;
    }
    .currently .swatch-link {
      display: inline-block;
      margin: 0 0 0 3px;
    }
    .currently .swatch-link:hover {
      border-color: #cccccc;
      cursor: default;
    }
    
    /* Other Swatch States */
    .configurable-swatch-list .hover .swatch-link,
    .configurable-swatch-list .selected .swatch-link,
    .swatch-link:hover {
      border-color: #3399cc;
    }
    
    .configurable-swatch-box {
      background: none !important;
    }
    .configurable-swatch-box select.swatch-select {
      display: none;
    }
    .configurable-swatch-box .validation-advice {
      margin: 0 0 5px;
      background: #df280a;
      padding: 2px 5px !important;
      font-weight: bold;
      color: #fff !important;
      float: left;
      display: block;
      border-radius: 3px;
    }
    .product-view .product-img-box .product-image img {
        max-width: 100%;
        max-height: 750px;
        margin: 0px auto;
    }
    .product-view .product-img-box .product-image-zoom {
        z-index: 0;
    }
    .product-view .product-image-thumbs img {
        max-width: 100%;
        max-height: 100%;
    }
    
  3. Copy the file

    skin/frontend/RWD/default/images/bg_x.png
    

    to

    skin/frontend/DEFAULT/default/images/
    

OTHER TIPS

your solution is great but not show color swatch in category list or grid. Here I add the solution to show it, tested on magento 1.9.2.4.

In : app/design/frontend/CUSTOM-THEME/template/catalog/product add followed line in list.phtml

1 - first to show in list view, check if there this, if no, update o change (aroud line 39):

<?php $_imgSize = 300; ?>
            <img id="product-collection-image-<?php echo $_product->getId(); ?>"
                 src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->keepFrame(false)->resize($_imgSize); ?>"
                 alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" />
        </a>

In alternative can use this:

            <img id="product-collection-image-<?php echo $_product->getId(); ?>"
          src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(230,279); ?>" class="small-image" 
          alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" />             

        </a>

adjust resize image.

2 - after "getRatingSummary" =php end if=, around line 53, add this:

                        <?php
                    // Provides extra blocks on which to hang some features for products in the list
                    // Features providing UI elements targeting this block will display directly below the product name
                    if ($this->getChild('name.after')) {
                        $_nameAfterChildren = $this->getChild('name.after')->getSortedChildren();
                        foreach ($_nameAfterChildren as $_nameAfterChildName) {
                            $_nameAfterChild = $this->getChild('name.after')->getChild($_nameAfterChildName);
                            $_nameAfterChild->setProduct($_product);
                            echo $_nameAfterChild->toHtml();
                        }
                    }
                    ?>

3 - make the same change to gird view around line 120 and 152.

4 - in the end of the file add this:

 <?php
// Provides a block where additional page components may be attached, primarily good for in-page JavaScript
if ($this->getChild('after')) {
    $_afterChildren = $this->getChild('after')->getSortedChildren();
    foreach ($_afterChildren as $_afterChildName) {
        $_afterChild = $this->getChild('after')->getChild($_afterChildName);
        //set product collection on after blocks
        $_afterChild->setProductCollection($_productCollection);
        echo $_afterChild->toHtml();
    }
}
?>

This was very helpful! I have some extra details that I was able to work through to get the image switching to work.

  1. Copy the file

    app/design/frontend/RWD/default/template/catalog/product/view/media.phtml
    

    to

    app/design/frontend/DEFAULT/default/template/catalog/product/view/
    

    or your custom theme

  2. Copy the following list of files:

    app/skin/frontend/RWD/default/js/app.js
    app/skin/frontend/RWD/default/js/slideshow.js
    app/skin/frontend/RWD/default/js/lib/* (all files and the elevatezoom folder)
    

    to

    app/skin/frontend/DEFAULT/default/js
    

    or your custom theme

  3. To include these new scripts, edit app/design/frontend/DEFAULT/default/layout/page.xml (make a backup of this file first and make sure to merge changes if you do updates as the default theme would be overwritten)

    Add after line 38:

    <action method="addJs"><script>lib/jquery/jquery-1.10.2.min.js</script></action>
    <action method="addJs"><script>lib/jquery/noconflict.js</script></action>
    

    Add after line 50 (line 52 if you've already added the above two lines):

        <action method="addItem"><type>skin_js</type><name>js/lib/modernizr.custom.min.js</name></action>
        <action method="addItem"><type>skin_js</type><name>js/lib/selectivizr.js</name></action>
        <action method="addItem"><type>skin_js</type><name>js/lib/matchMedia.js</name></action>
        <action method="addItem"><type>skin_js</type><name>js/lib/matchMedia.addListener.js</name></action>
        <action method="addItem"><type>skin_js</type><name>js/lib/enquire.js</name></action>
        <action method="addItem"><type>skin_js</type><name>js/app.js</name></action>
        <action method="addItem"><type>skin_js</type><name>js/lib/jquery.cycle2.min.js</name></action>
        <action method="addItem"><type>skin_js</type><name>js/lib/jquery.cycle2.swipe.min.js</name></action>
        <action method="addItem"><type>skin_js</type><name>js/slideshow.js</name></action>
        <action method="addItem"><type>skin_js</type><name>js/lib/imagesloaded.js</name></action>
    
  4. Remove the /* Product Images */ section from your styles.css file (around lines 783-803) and paste in the following CSS from the RWD styles.css file:

    * Product Images */
    .product-img-box {
      width: 50%;
      float: left;
    }
    .product-img-box .product-name h1 {
      border: 0;
    }
    .product-img-box .product-image {
      margin-bottom: 10px;
    }
    .product-img-box .product-image img {
      max-width: 100%;
      max-height: 750px;
      margin: 0px auto;
    }
    
    @media only screen and (max-width: 479px) {
      .product-img-box .product-image img {
        max-height: 450px;
      }
    }
    .product-image-gallery {
      position: relative;
    }
    .product-image-gallery .gallery-image {
      display: none;
    }
    .product-image-gallery .gallery-image.visible {
      display: block;
    }
    .product-image-gallery .gallery-image.visible.hidden {
      visibility: hidden;
    }
    .product-image-gallery:before, .product-image-gallery:after {
      content: '';
      position: absolute;
      top: 0px;
      left: 0px;
      width: 100%;
      height: 100%;
      display: none;
    }
    .product-image-gallery:before {
      background-color: white;
      opacity: 0.8;
      z-index: 2;
    }
    .product-image-gallery:after {
      background-image: url("../images/opc-ajax-loader.gif");
      background-repeat: no-repeat;
      background-position: center;
      z-index: 3;
    }
    .product-image-gallery.loading {
      position: relative;
    }
    .product-image-gallery.loading:before, .product-image-gallery.loading:after {
      display: block;
    }
    
    .product-image-thumbs li {
      display: inline-block;
    }
    .product-image-thumbs li:first-child {
      margin-left: -1px;
    }
    .product-image-thumbs a {
      display: inline-block;
      border: 1px solid transparent;
    }
    
    .no-touch .product-image-thumbs a:hover {
      border-color: #c7c7c7;
    }
    

Last, but not least, some optimizations to the elevateZoom thanks to Google and finding the following post at BelVG Blog by Mishel Soiko, I was able to modify and take advantage of more settings for the elevateZoom such as internal zoom or offset of the zoom window, etc. Also, I wanted the image to have a popup fancybox when clicked, which I enabled with help from the above blog down in the comments.

  1. Open that app.js file you copied over to your theme earlier

    Above line 1153 (var ProductMediaManager = {), paste in (copied from the above BelVG blog link):

    var settings = {
    
        // set tint background
        tint:true,
        tintColour:'#F90',
        tintOpacity:0.5,
    
        // Size
        zoomWindowHeight: 300,
        zoomWindowWidth: 400,
        borderSize: 0,
    
        // Position
        zoomWindowOffetx: 10,
        zoomWindowOffety: 0,
    
        // Additional settings for Zoomer positioning.
        // zoomWindowPosition: 1,
        // zoomType: "inner",
    
        // Fade-in speed settings
        zoomWindowFadeIn: 500,
        zoomWindowFadeOut: 500,
        lensFadeIn: 500,
        lensFadeOut: 500,
    
        // Ability to zoom by using the mouse scroll.
        scrollZoom : true,
    
        // inertia - my favorite one 
        easing: true
    }
    

    If you want the fancybox popup, at above what is now line 1227, paste in:

    $j(".product-image-gallery").on("click", function(e) {
        var src = $j('.product-image img.visible').attr('src');
    $j.fancybox(src);
    });
    

    Note, you'll need to have the fancybox js library loading after jQuery in your page.xml or elsewhere in your theme

    Finally, modify what is now line 1232 (if you did both pastings from above) from:

    image.elevateZoom();
    

    to:

    image.elevateZoom(settings);
    

For an overview of all the zoomer settings, check out the official page describing the elevateZoom Settings

And that should get it working. If you're working with a custom theme (as I was) you may have more to do.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top