Create Custom Tiles using HTML CSS and KnockoutJS in SharePoint 2013

This SharePoint tutorial, we will discuss, how to create custom promoted links or Tiles in SharePoint 2013/2016 with custom sorting using Knockout JS and csom.

Technologies Used:

  • HTML CSS for building tile like structure.
  • CSOM to get data from the SharePoint list.
  • Knockout JS for binding list data with UI

Pre-Requisite:

  • Add the Promoted links app on your site. (I have given it name as “CustomTiles”). You can use a custom list as well with the same columns as in promoted links.
  • Add picture library for background images of promoted links. (Given name as “picsForTiles”).
  • Add some data in the promoted links app i.e “CustomTiles” list.

Below is a screenshot with some random data:

create custom tiles using knockout js in sharepoint
create custom tiles using knockout js in sharepoint 2013

HTML:

Add following HTML with required files in HTML file.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<html>
<head>
<title>Custom Promoted Links</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="/SiteAssets/JS/getTilesData.js"></script>
<link rel="stylesheet" href=" /SiteAssets/CSS/customTiles.css"/>
</head>
<body>
<!–HTML Content–>
<input type="button" value="Sort By Title" data-bind="click: sortedtilesByTitle()">&nbsp; <input type="button" value="Sort By Order" data-bind="click: sortedtilesByOrder()"><br/><br/>
<div class="mainContainer" data-bind="foreach:tiles">
<div class='card slide-up'>
<div ><img class='image' data-bind="attr:{src: backImage}"> </div>
<div class='caption'> <h2 class='caption-title' data-bind="text:title"></h2>
<p class='caption-content' data-bind="text:desc"> </p>
</div> </div> </div>
</body> </html>

CSS:

Content of customTiles.css file:

.card {
position: relative;
width: 200px;
height: 200px;
float:left;
margin:0 10px 10px 0;
cursor:pointer;
background-color: #ffffff;
overflow: hidden;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
}
.image {
width:200px;
height:200px;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
-webkit-transition-property: -webkit-transform;
transition-property: -webkit-transform;
transition-property: transform;
transition-property: transform, -webkit-transform;
-webkit-transition-duration: 0.4s;
transition-duration: 0.4s;
}
.caption {
position: absolute;
top: auto;
bottom: 0;
opacity: 0;
left: 0;
width: 100%;
height: 100px;
background-color: #ffffff;
padding: 15px;
-webkit-transform: translateY(100%);
transform: translateY(100%);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transition: opacity 0.1s 0.3s, -webkit-transform 0.4s;
transition: opacity 0.1s 0.3s, -webkit-transform 0.4s;
transition: transform 0.4s, opacity 0.1s 0.3s;
transition: transform 0.4s, opacity 0.1s 0.3s, -webkit-transform 0.4s;
}
.caption-title {
margin-top: 0;
margin-bottom: 10px;
}
.caption-content {
margin: 0;
}
.caption-link {
color: #724b31;
text-decoration: none;
opacity: 1;
-webkit-transition-property: opacity;
transition-property: opacity;
-webkit-transition-duration: 0.15s;
transition-duration: 0.15s;
-webkit-transition-timing-function: cubic-bezier(0.39, 0.58, 0.57, 1);
transition-timing-function: cubic-bezier(0.39, 0.58, 0.57, 1);
}
.caption-link:hover {
opacity: 0.65;
}
.slide-up:hover .image {
-webkit-transform: translateY(-50px);
transform: translateY(-50px);
}
.slide-up:hover .caption {
opacity: 1;
-webkit-transform: translateY(0px);
transform: translateY(0px);
-webkit-transition: opacity 0.1s, -webkit-transform 0.4s;
transition: opacity 0.1s, -webkit-transform 0.4s;
transition: transform 0.4s, opacity 0.1s;
transition: transform 0.4s, opacity 0.1s, -webkit-transform 0.4s;
}

JavaScript (gettilesData.js):

I have used knockout js for binding and logic as follows which is self-explanatory.

//declare variables
var completeListItems=null;
var listName='CustomTiles';
$(document).ready(function ()
{
//fetch items from list on page load
SP.SOD.executeFunc(‘sp.js', ‘SP.ClientContext', function () { mainFunction(); });
});

//main function to activate knockout
function mainFunction(){
completeListItems=new tilesListViewModel();
retrivelistItems();
ko.applyBindings(completeListItems);
}

function tilesList(title,desc,tileOrder, backImage, linkLocation) {
var self = this;
self.title = title;
self.desc = desc;
self.tileOrder = tileOrder;
self.backImage = backImage;
self.linkLocation=linkLocation;
}

//view model
function tilesListViewModel() {
var self = this;
self.tiles = ko.observableArray([]); //observable array
//to add tiles data
self.AddTiles = function (title,desc,tileOrder, backImage, linkLocation) {
self.tiles.push(new tilesList(title,desc,tileOrder, backImage, linkLocation));}
//sort tiles by order
self.sortedtilesByOrder = function() {
self.tiles.sort(function (left, right) {
return left.tileOrder == right.tileOrder ? 0 : (left.tileOrder < right.tileOrder ? -1 : 1) });
}
//sort tiles by title
self.sortedtilesByTitle = function() {
self.tiles.sort(function (left, right) {
return left.title == right.title ? 0 : (left.title < right.title ? -1 : 1) });
}

}//End view model

//function to get list items from sharepoint using CSOM
function retrivelistItems(){
var clientContext=new SP.ClientContext.get_current();
var oList=clientContext.get_web().get_lists().getByTitle(listName);
var camlQuery= new SP.CamlQuery();
camlQuery.set_viewXml("<View><RowLimit>20</RowLimit></View>");
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(Function.createDelegate(this,this.querySuccess),Function.createDelegate(this,this.queryFail));
}

//success callback
function querySuccess(sender,args){

var listItemEnumerator = collListItem.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
var tileTitle=oListItem.get_item(‘Title');
var tileDesc=oListItem.get_item(‘Description');
var tileOrder=oListItem.get_item(‘TileOrder');
var tileBackImage=oListItem.get_item(‘BackgroundImageLocation').get_url();
var linkLoc=oListItem.get_item(‘LinkLocation').get_url();
//fill the data from list
completeListItems.AddTiles(tileTitle,tileDesc,tileOrder,tileBackImage,linkLoc);
}
}

//failure function callback
function queryFail(sender,args){
alert(‘Request failed. ‘ + args.get_message() + ‘\n' + args.get_stackTrace());
}

Add the Content Editor web part to the SharePoint page and refer HTML file. The end result will be as follows:

create custom tiles using knockout js in sharepoint 2016

On mouse hover tile displays Title and description. You can add more data from the list if required.

create custom tiles using knockout js in sharepoint online

Clicking on sort by title or sort by the order will sort the tiles according to title (A-Z) or order provided in the list (1-onwards sequentially). You can customize CSS for more transition effects.

You may like following SharePoint tutorials:

This SharePoint tutorial we learned how to create custom Tiles using HTML CSS and KnockoutJS in SharePoint 2013/2016.

Donwload Hub site pdf

Download SharePoint Online Tutorial PDF FREE!

Get update on Webinars, video tutorials, training courses etc.

>