UGC Techdocs
  • Introduction
  • Guides
    • Analytics
      • Tracking UGC on Adobe Analytics
      • Tracking Widget interactions with Google Analytics
    • Direct Uploader
      • How to add Custom Data to Direct Uploader
      • How to capture Custom Data on Direct Uploader
      • How to automatically tag data on Direct Uploader
      • How to Customize error messages on Direct Uploader
      • How to Track Direct Uploader form submissions with Google Analytics (Universal & GA 4)
    • Data Templates
      • Creating a Data Template
    • Rights via Registration
      • Capture Custom Data on Rights by Registration Form
      • Styling Rights via Registration Form
    • REST API
      • Caching REST API results for optimization
      • Posting content into Nosto via Tile API
      • Posting images into Nosto via Tile API
    • Onsite Widgets (2.0)
      • Blank Canvas
        • How to Use the Blank Canvas to Create a Twitter Count Widget
        • Creating an Auto-Scrolling Carousel using Blank Canvas
        • Creating Gallery Widget by Using the Blank Canvas Widget
        • Creating a simple Hover effect using Blank Canvas
        • Creating a Word Cloud using Blank Canvas
        • Creating Your Widget by Using the Blank Canvas
      • Bind your own Events
      • Creating a Grid Widget from Waterfall
      • Create a Q&A Widget using Data Templates
      • Displaying a Widget in a Mobile App
      • Dynamically Specify Products to Display in Widget
      • Dynamically specify what Tile to display in a Widget
      • How to add a title / subtitle to a widget
      • How to localize the load more button on widgets
      • How to overlay existing Google Map with the UGC Map Widget
      • How to use Filter and search in a Widget
      • How to change click on inline tile behaviour to redirect to PDP in a Widget
      • Styling cross-sellers on Grid and Carousel Widgets
      • How to Load External JS and CSS into Widgets
      • Profiling Widget Performance
      • Re-targeting with Widgets and Facebook Pixel
      • Render Widget filters dynamically
      • Styling Carousel Widget
      • Styling Grid Widget
      • Styling Masonry Widget
      • Styling Waterfall Widget
      • Styling Widget Expanded Tile
      • Styling Widget Shopspots
      • Using Web Fonts in Widgets
    • Digital Screens
      • Customizing Carousel Event Screen
      • Customizing Mosaic Event Screen
      • Customizing Scrollwall Event Screen
      • Customizing the Mosaic Event Screen to Have 9 Even Tiles
    • Email
      • Adding Location to an Email Tile
      • Styling the Email Widget
    • Integrations
      • DoubleClick
        • UGC Ads with Nosto and Google DoubleClick
      • Zapier
        • Consuming UGC Webhooks via Zapier
      • Mailchimp
        • Bring Social Content into a Mailchimp Campaign
    • Webhooks
      • Trigger notifications when content is in the moderation queue
  • Widgets
  • API Docs
    • JavaScript API
      • Widgets
        • Introduction
        • API Reference for Content Widgets
        • API Reference for Blank Canvas
        • API Reference for Map Widget
      • Digital Screens
        • Introduction
        • API Reference
    • Content API
      • Reference
    • REST API
      • Reference
        • Filters API
        • Moderation Views API
        • Tags API
        • Terms API
        • Tiles API
        • Users API
        • Widgets API
        • Automation Rules API
        • REST API Reference Widgets style and config
      • Best Practices
    • Webhooks
  • Enterprise Tools
    • Automation Rules
      • Triggers
      • Actions
      • Samples
    • Data Templates
    • User Access Control (UAC)
    • Single Sign On (SSO)
    • Enterprise Admin User Interface (EAUI)
    • Zapier
  • Commerce Tools
    • Product Feeds
    • Widget Implementation
    • Reporting
    • Integrations
      • Google Tag Manager
      • Magento
      • SalesForce Commerce Cloud
      • Shopify
      • Shopify Add To Cart
        • Global Variant Mapping for Add to Cart
        • Customise Add to Cart Widget Experience
  • Analytics
    • Google Analytics 4
      • Getting Started
      • Widgets Events
      • E-commerce Events
      • Email Events
  • Terms of Use
Powered by GitBook
On this page
  • Overview
  • Layout
  • Tile
  • CSS
  • Javascript
  • Final Result

Was this helpful?

  1. Guides
  2. Onsite Widgets (2.0)
  3. Blank Canvas

Creating an Auto-Scrolling Carousel using Blank Canvas

PreviousHow to Use the Blank Canvas to Create a Twitter Count WidgetNextCreating Gallery Widget by Using the Blank Canvas Widget

Was this helpful?

Overview

Nosto's UGC Blank Canvas Widget allows users to very quickly and easily design their own Widget templates to suit their organisation's requirements.

In this guide we are going to create a Carousel Widget, which has been optimised for Tablet and Mobile devices and leverages to create not only a smooth scroll, but also some auto-scrolling behaviour.

In the guide we are going to move through each of the Mustache Partials to build the final Widget.

Layout

First Step is to build out our Layout partial. Here we are going to load the SVG elements for the left and right arrow and then define the container which will hold the Tiles.

<section class="some no-touchevents">
    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;" baseProfile="tiny" version="1.2">
        <symbol id="icon-arrow-left" viewBox="0 0 64 64">
            <title>Arrow Left</title>
            <desc>Scroll Left</desc>
            <polygon points="43,12 36,8 20,32 36,56 43,52 30,32 "></polygon>
        </symbol>
        <symbol id="icon-arrow-right" viewBox="0 0 64 64">
            <title>Arrow Right</title>
            <desc>Scroll Right</desc>
            <polygon points="20,12 27,8 43,32 27,56 20,52 33,32 "></polygon>
        </symbol>
    </svg>
    <main>
        <section>
            <div class="container" id="mouseovercapture">
                <div class="swiper">
                    <div class="some__slider-container swiper-container swiper-container-horizontal swiper-container-rtl" dir="rtl">
                        <ul class="swiper-wrapper some__track">
                            {{#tiles}}
                                <li class="swiper-slide" style="width: 275px; margin-left: 15px;">
                                {{>tpl-tile}}
                                </li>
                            {{/tiles}}
                        </ul>
                    </div>
                    <div class="swiper-navigation">
                        <div class="previous">
                            <svg class="icon">
                                <use xlink:href="#icon-arrow-right"></use>
                            </svg>
                        </div>
                        <div class="next">
                            <svg class="icon">
                                <use xlink:href="#icon-arrow-left"></use>
                            </svg>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </main>
</section>

Tile

Next step is defining our Tile partial. In this Widget, for our Tiles we simply wish to load the relevant Tile image in the background, and then on mouse-over include the Content Creator, the Tile Message and provide a link back to the original Tile on Social Media.

<a target="_blank" href="{{original_url}}" class="tile swiper-lazy swiper-lazy-loaded" style="background-image: url('{{image}}');">
	<p><span class="account">@{{user}}</span>{{{message}}}</p>
</a>

CSS

@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700');	
body {
	font-family: 'Open Sans', sans-serif;
	height: 250px;
}
.swiper-slide,
    .swiper-wrapper {
        width: 100%;
        height: 100%;
        position: relative
    }
    .swiper .swiper-navigation .next,
    .swiper-container-no-flexbox .swiper-slide {
        float: left
    }
    .swiper-container {
        margin: 0 auto;
        position: relative;
        overflow: hidden;
        z-index: 1
    }
    .swiper-container-vertical>.swiper-wrapper {
        -ms-flex-direction: column;
        -webkit-flex-direction: column;
        flex-direction: column
    }
    .swiper-wrapper {
        z-index: 1;
        display: -ms-flexbox;
        display: -webkit-flex;
        display: flex;
        transition-property: -webkit-transform;
        transition-property: transform;
        transition-property: transform, -webkit-transform;
        box-sizing: content-box
    }
    .swiper-container-android .swiper-slide,
    .swiper-wrapper {
        -webkit-transform: translate3d(0, 0, 0);
        -ms-transform: translate3d(0, 0, 0);
        transform: translate3d(0, 0, 0)
    }
    .swiper-container-multirow>.swiper-wrapper {
        -webkit-box-lines: multiple;
        -moz-box-lines: multiple;
        -ms-flex-wrap: wrap;
        -webkit-flex-wrap: wrap;
        flex-wrap: wrap
    }
    .swiper-container-free-mode>.swiper-wrapper {
        transition-timing-function: ease-out;
        margin: 0 auto
    }
    .swiper-slide {
        -webkit-flex-shrink: 0;
        -ms-flex: 0 0 auto;
        -ms-flex-negative: 0;
        flex-shrink: 0
    }
    .swiper-container-autoheight,
    .swiper-container-autoheight .swiper-slide {
        height: auto
    }
    .swiper-container-autoheight .swiper-wrapper {
        -ms-flex-align: start;
        -webkit-align-items: flex-start;
        -ms-grid-row-align: flex-start;
        align-items: flex-start;
        transition-property: height, -webkit-transform;
        transition-property: transform, height;
        transition-property: transform, height, -webkit-transform
    }
    .swiper-container .swiper-notification {
        position: absolute;
        left: 0;
        top: 0;
        pointer-events: none;
        opacity: 0;
        z-index: -1000
    }
    .swiper-wp8-horizontal {
        -ms-touch-action: pan-y;
        touch-action: pan-y
    }
    .swiper-wp8-vertical {
        -ms-touch-action: pan-x;
        touch-action: pan-x
    }
    .swiper-button-next,
    .swiper-button-prev {
        position: absolute;
        top: 50%;
        width: 27px;
        height: 44px;
        margin-top: -22px;
        z-index: 10;
        cursor: pointer;
        background-size: 27px 44px;
        background-position: center;
        background-repeat: no-repeat
    }
    .swiper-button-next.swiper-button-disabled,
    .swiper-button-prev.swiper-button-disabled {
        opacity: .35;
        cursor: auto;
        pointer-events: none
    }
    .swiper-pagination {
        position: absolute;
        text-align: center;
        transition: .3s;
        -webkit-transform: translate3d(0, 0, 0);
        -ms-transform: translate3d(0, 0, 0);
        transform: translate3d(0, 0, 0);
        z-index: 10
    }
    .swiper-pagination.swiper-pagination-hidden {
        opacity: 0
    }    
    .swiper-container-coverflow .swiper-wrapper,
    .swiper-container-flip .swiper-wrapper {
        -ms-perspective: 1200px
    }
    .swiper-container-cube,
    .swiper-container-flip {
        overflow: visible
    }
    .swiper-container-cube .swiper-slide,
    .swiper-container-flip .swiper-slide {
        pointer-events: none;
        -webkit-backface-visibility: hidden;
        backface-visibility: hidden;
        z-index: 1
    }
    .swiper-container-cube .swiper-slide .swiper-slide,
    .swiper-container-flip .swiper-slide .swiper-slide {
        pointer-events: none
    }
    .swiper-container-cube .swiper-slide-active,
    .swiper-container-cube .swiper-slide-active .swiper-slide-active,
    .swiper-container-flip .swiper-slide-active,
    .swiper-container-flip .swiper-slide-active .swiper-slide-active {
        pointer-events: auto
    }
    .swiper-container-cube .swiper-slide-shadow-bottom,
    .swiper-container-cube .swiper-slide-shadow-left,
    .swiper-container-cube .swiper-slide-shadow-right,
    .swiper-container-cube .swiper-slide-shadow-top,
    .swiper-container-flip .swiper-slide-shadow-bottom,
    .swiper-container-flip .swiper-slide-shadow-left,
    .swiper-container-flip .swiper-slide-shadow-right,
    .swiper-container-flip .swiper-slide-shadow-top {
        z-index: 0;
        -webkit-backface-visibility: hidden;
        backface-visibility: hidden
    }
    .swiper-container-cube .swiper-slide {
        visibility: hidden;
        -webkit-transform-origin: 0 0;
        -ms-transform-origin: 0 0;
        transform-origin: 0 0;
        width: 100%;
        height: 100%
    }
    .swiper-container-cube.swiper-container-rtl .swiper-slide {
        -webkit-transform-origin: 100% 0;
        -ms-transform-origin: 100% 0;
        transform-origin: 100% 0
    }
    .swiper-container-cube .swiper-slide-active,
    .swiper-container-cube .swiper-slide-next,
    .swiper-container-cube .swiper-slide-next+.swiper-slide,
    .swiper-container-cube .swiper-slide-prev {
        pointer-events: auto;
        visibility: visible
    }
    .swiper-container-cube .swiper-cube-shadow {
        position: absolute;
        left: 0;
        bottom: 0;
        width: 100%;
        height: 100%;
        background: #000;
        opacity: .6;
        -webkit-filter: blur(50px);
        filter: blur(50px);
        z-index: 0
    }
    .swiper-container-fade.swiper-container-free-mode .swiper-slide {
        transition-timing-function: ease-out
    }
    .swiper-container-fade .swiper-slide {
        pointer-events: none;
        transition-property: opacity
    }
    .swiper-container-fade .swiper-slide .swiper-slide {
        pointer-events: none
    }
    .swiper-container-fade .swiper-slide-active,
    .swiper-container-fade .swiper-slide-active .swiper-slide-active {
        pointer-events: auto
    }
    .swiper-scrollbar {
        border-radius: 10px;
        position: relative;
        -ms-touch-action: none;
        background: rgba(0, 0, 0, .1)
    }
    .swiper-container-horizontal>.swiper-scrollbar {
        position: absolute;
        left: 1%;
        bottom: 3px;
        z-index: 50;
        height: 5px;
        width: 98%
    }
    .swiper-container-vertical>.swiper-scrollbar {
        position: absolute;
        right: 3px;
        top: 1%;
        z-index: 50;
        width: 5px;
        height: 98%
    }
    .swiper-scrollbar-drag {
        height: 100%;
        width: 100%;
        position: relative;
        background: rgba(0, 0, 0, .5);
        border-radius: 10px;
        left: 0;
        top: 0
    }
    .swiper-scrollbar-cursor-drag {
        cursor: move
    }
    
    @-webkit-keyframes swiper-preloader-spin {
        100% {
            -webkit-transform: rotate(360deg)
        }
    }
    @keyframes swiper-preloader-spin {
        100% {
            -webkit-transform: rotate(360deg);
            transform: rotate(360deg)
        }
    }
    html:after {
        content: "breakpoint-getComputedStyleTest";
        display: none
    }
    & {
        overflow-x: hidden;
        background: #eee;
        color: #000;
        font-family: 'Open Sans', sans-serif;
		font-size: 5px;
        line-height: 1.667em;
        margin: 0;
        padding: 70px 0 100px
    }
    &:after {
        content: "none";
        display: none
    }
    & .js-breakpoint-none {
        position: absolute
    }
    &.whitebg {
        background: #fff
    }
    *,
    :after,
    :before {
        box-sizing: border-box;
        -moz-box-sizing: border-box
    }
    @media (min-width: 480px) {
        &:after {
            content: "w480";
            display: none
        }
        & .js-breakpoint-w480 {
            position: absolute
        }
    }
    @media (min-width: 768px) {
        &:after {
            content: "w768";
            display: none
        }
        & .js-breakpoint-w768 {
            position: absolute
        }
    }
    @media (min-width: 980px) {
        &:after {
            content: "w980";
            display: none
        }
        & .js-breakpoint-w980 {
            position: absolute
        }
    }
    @media (min-width: 1024px) {
        &:after {
            content: "w1024";
            display: none
        }
        & .js-breakpoint-w1024 {
            position: absolute
        }
    }
    .swiper {
        position: relative
    }
    .swiper .swiper-container {
        width: 100%
    }
    .swiper .swiper-container .swiper-wrapper {
        list-style: none;
        padding: 0;
        margin: 0;
        will-change: transform;
        transition-timing-function: cubic-bezier(.25, .46, .45, .94)
    }
    .swiper .swiper-container .swiper-wrapper .swiper-slide {
        width: 240px;
        position: relative;
        transition: -webkit-transform .9s ease-out;
        transition: transform .9s ease-out;
        transition: transform .9s ease-out, -webkit-transform .9s ease-out;
        -webkit-transform: scale(.92);
        -ms-transform: scale(.92);
        transform: scale(.92)
    }
    @media (min-width: 480px) {
        .swiper .swiper-container .swiper-wrapper .swiper-slide {
            -webkit-transform: scale(1);
            -ms-transform: scale(1);
            transform: scale(1)
        }
    }
    .swiper .swiper-container .swiper-wrapper .swiper-slide.swiper-slide-active {
        -webkit-transform: scale(1);
        -ms-transform: scale(1);
        transform: scale(1)
    }
    .swiper .swiper-navigation {
        display: none;
        position: absolute;
        left: -65px;
        right: -65px;
        top: 50%;
        -webkit-transform: translateY(-50%);
        -ms-transform: translateY(-50%);
        transform: translateY(-50%)
    }
    @media (min-width: 480px) {
        .swiper .swiper-navigation {
            display: block
        }
    }
    .swiper .swiper-navigation .next.swiper-button-disabled,
    .swiper .swiper-navigation .previous.swiper-button-disabled,
    .swiper .tile .swiper-lazy-preloader {
        display: none
    }
    .swiper .swiper-navigation .next,
    .swiper .swiper-navigation .previous {
        cursor: pointer;
        font-size: 34px;
        fill: #a5a5a5;
        width: 75px;
        will-change: fill;
        transition: fill .33s ease-out
    }
    .swiper .swiper-navigation .next .icon,
    .swiper .swiper-navigation .previous .icon {
        width: 100%
    }
    .swiper .swiper-navigation .next:hover,
    .swiper .swiper-navigation .previous:hover {
        fill: #999
    }
    .swiper .swiper-navigation .previous {
        float: right
    }
    .swiper .tile.swiper-lazy-loading .swiper-lazy-preloader {
        display: block
    }
    .tile .buttonplay,
    &.no-touchevents .tile p {
        will-change: opacity;
        transition: opacity .25s ease-out
    }
    .tile {
        display: block;
        position: relative;
        width: 100%;
        height: 100%;
        text-align: left;
        color: #000;
        background: #fff;
        overflow: hidden;
        background-size: cover;
        text-decoration: none
    }
    &.no-touchevents .tile:hover p {
        opacity: 1
    }
    &.no-touchevents .tile:hover .buttonplay {
        opacity: 0
    }
    &.no-touchevents .tile p {
        opacity: 1;
        color: #000;
    }
    &.no-touchevents .tile.swiper-lazy p {
        opacity: 0
    }
    &.no-touchevents .tile.swiper-lazy:hover:after {
        color: #b8b9ba
    }
    &.no-touchevents .tile.swiper-lazy:hover p {
        opacity: 1
    }
    .tile:before {
        content: "";
        display: block;
        padding-bottom: 100%
    }
    .tile span,
    .tile svg {
        pointer-events: none
    }
    .tile .buttonplay {
        fill: #fff;
        position: absolute;
        top: 50%;
        left: 50%;
        margin: -40px 0 0 -40px;
        width: 80px;
        height: 80px
    }
    .tile p {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: 0;
        padding: 15px;
        direction: ltr;
        background: rgba(255, 255, 255, .8);
        height: 100%;
        font-size: 18px;
        line-height: 1.33;
        transition: opacity .2s;
        opacity: 0
    }
    .tile p .account,
    .tile p .date {
        display: none
    }
    .swiper-container.small .tile p {
        font-size: 16px
    }
    @media (min-width: 768px) {
        .swiper-container.small .tile p {
            padding: 10px
        }
        .tile p {
            padding: 25px
        }
        .tile p .account {
            display: block;
            font-weight: 700;
            margin: 0 0 10px;
            text-transform: uppercase
        }
        .tile p .date {
            display: block;
            font-size: 15px
        }
    }
    .container {
        max-width: 1275px;
        margin: 0 auto;
        padding: 0 12.5px
    }
    @media (min-width: 480px) {
        .container {
            padding: 0 65px
        }
    }
    .nowrap {
        white-space: nowrap
    }
    .hidden {
        display: none
    }
p {
	font-size: 14px !important;
}

Javascript

Stackla.loadJS(['https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.3.1/js/swiper.min.js']).then(function() {
	Stackla.loadTilesByFilter(function (tiles) {
		Stackla.render({tiles: tiles});
		var swiper = new Swiper ('.some__slider-container', {
        slidesPerView: 4,
        spaceBetween: 15,
        centeredSlides: !1,
        slideToClickedSlide: !1,
        lazyLoading: !0,
        preloadImages: !1,
        nextButton: ".next",
        prevButton: ".previous",
        observer: !0,
        watchSlidesProgress: !0,
        watchSlidesVisibility: !0,
        updateOnImagesReady: !0,
        speed: 400,
        autoplay: 3e3,
        autoplayDisableOnInteraction: !1,
        loop: !0,
        breakpoints: {
            1024: {
                slidesPerView: 3
            },
            768: {
                slidesPerView: 2,
                centeredSlides: !1,
                spaceBetween: 15,
                slideToClickedSlide: !1
            },
            480: {
                slidesPerView: 1.5,
                centeredSlides: !0,
                spaceBetween: 0,
                slideToClickedSlide: !0
            }
        }
    });
	console.log(swiper);
	});
});

Final Result

The final result should look similar to the Widget below with the auto-scrolling Carousel being responsive for Tablet and Mobile outputs as well.

<script type="text/javascript">
    (function (d, id) { var t, el = d.scripts[d.scripts.length - 1].previousElementSibling; 
        if (el) el.dataset.initTimestamp = (new Date()).getTime(); 
        if (d.getElementById(id)) return; t = d.createElement('script'); 
        t.src = '//assetscdn.stackla.com/media/js/widget/fluid-embed.js'; 
        t.id = id; (d.getElementsByTagName('head')[0] 
                || d.getElementsByTagName('body')[0]).appendChild(t); 
    }
    (document, 'stackla-widget-js'));</script>

Next step is our styling. A number of the below styling elements are influenced from the documentation and can be customised to suit your design preferences.

Finally is the Javascript. First step is loading the library. For this Widget we have loaded it from and then defined our variables such as where to load from, speed of scroll and the mobile breakpoints.

Swiper by idangero.us
Swiper by idangero.us
cdnjs
Swiper by idangero.us
Overview
Layout
Tile
CSS
Javascript
Final Result
Back to Top
Back to Top
Back to Top
Back to Top
Back to Top