Me & My SharePoint [FrontEnd]

© Christian Stahl – All about SharePoint branding & customizations

Nominated as a top SharePoint influencer for harmon.ie’s annual Top 25 SharePoint influencer initiative — August 11, 2016

Nominated as a top SharePoint influencer for harmon.ie’s annual Top 25 SharePoint influencer initiative

Of course, it’s nice to have been nominated and acclaimed addition to activity in the great SharePoint Community amongs all the other SP dudes in that list. Community voting will run August 1 – 19. Now my friends, time to vote  🙂

Vote here 

Btw, what happens otherwise? Since I’ve started up my own company for 1 1/2 years ago, I have had very little time to write blog posts, it has been super busy with various assignments. Anyway, I have ideas for new stuff on the front end scoop of SharePoint and hope soon to have time to write down what I think some interesting articles on the subject. I will have two sessions on SEF in 26-28 October in Stockholm, Sweden about SP Addins and Display templates, so probably I will stock up on some articles about this in soon. In the meantime, stay in tune!

 

SEF Unity Connect Logo no AZURE-updated

</ christian>

 

 

How to create a text-size switcher in SharePoint with HTML5 Web storage — March 31, 2015

How to create a text-size switcher in SharePoint with HTML5 Web storage

I’ve written a couple of post earlier about how to work with JS and cookies, that’s cool but now in the era of the client side it’s time to take a look into how to work with HTML5 Web Storage and Local Storage and in the example, how to create a simple text-size switcher.

What is Web Storage and what can we do with it?

Ok, with local storage, a web application like SharePoint can store data locally within the user’s browser. Before HTML5, app data had to be stored in cookies, included in every server request. Local storage is more secure, and large amounts of data can be stored locally, without affecting website performance.
Yeah localStorage works somewhat like a database; it stores some data locally on the user’s browser, which then can be retrieved using JavaScript. The data will always be available in the user’s browser, even after the user has closed the browser.

There are many different ways you could use web storage, like:

  • Navigation: Remember the last state, add an active class into the DOM
  • Forms: Remember form values
  • Branding: Let the user decide things like an alternate CSS (style sheet switcher)
  • WebService calls: If something doesn’t change then there is no point in loading it over the Internet compared to local access which is so much faster

Local Storage v/s Cookie

Cookies, the old way of saving data are primarily for reading server-side. Local storage can only be read client-side, so if you need to create a function for the client and not for the server, use Local Storage. Got it? The Local Storage stays on the client, while cookies are sent to the server through the HTTP header. Cookies are not considered secure and not able to hold much data either.

More to note

The Local Storage stores data with no expiration date and gets cleared only through JavaScript or by clearing the Browser Cache or Locally Stored Data, unlike cookie expiry. There’s two kind of ‘storage objects’, Local and Session (storage). A Local storage will keep the data stored when you close the tab or a the broser window and the Session storage will not keep anything stored. Local Storage comes with HTML5, so if you need to create an app supporting really old browsers (for example IE7) you can use cookies as a fallback by for example modernizr as the detector. However Local Storage are a part of the HTML5 specs, so if you allow HTML5 in your master page, which comes out of the box in SharePoint 2013 and the users have IE8, latest Google Chrome, Safari, Firefox etc your ready to go!

Demo: Create a text-size switcher

This example will change the SharePoint body font size from small to large in Three steps. This will work in SharePoint 2013, onprem or Online. I’ve tested this in IE11 and latest Google Chrome. Take a look at a video of the text-size switcher. Click at the SWF file and open it.

I’ll just provide you the HTML, CSS and JS – you could implement this in a custom masterpage, APP or for example in a text file linked from a content editor web part. In this case I’m using _spBodyOnLoadFunctionNames and if your using a custom master page, be sure to include a reference to an external JS file in the bottom of the master page, just above the ending body tag. Keep the reference to jQuery in the head section of your master page. You can download a masterpage with a css file and js file if you need to take a look from here.

Markup

<div class="radioFontHolders">
<div class="letterFontsHolder">
<div class="miniLetter">Aa</div>
<div class="midLetter">Aa</div>
<div class="bigLetter">Aa</div>
<div style="clear:both"></div>
</div>           
<div class="radioHolders">
<input type="radio" id="radio-1-1" name="radio-1-set" class="regular-radio" value="miniFont" /><label for="radio-1-1"></label>
<input type="radio" id="radio-1-2" name="radio-1-set" class="regular-radio" value="midFont" /><label for="radio-1-2"></label>
<input type="radio" id="radio-1-3" name="radio-1-set" class="regular-radio" value="maxFont" /><label for="radio-1-3"></label>
</div>
</div>

JS

// Using SP JS API to push the function instead of document ready or window load
_spBodyOnLoadFunctionNames.push("Demo.Intranet.Contrast");

// Establish Namespace
Type.registerNamespace('Demo')
Demo.Intranet = Demo.Intranet || {};

// start set contrast ---
Demo.Intranet.Contrast = function () {

jQuery('.radioHolders input').click(function () {
var fontCode = jQuery(this).val();
if (fontCode == 'miniFont'){
jQuery('#miniFont').attr("checked", "checked");
jQuery("body").removeClass("midFont MaxFont").addClass("miniFont");
}
else if (fontCode == 'midFont'){
jQuery('#midFont').attr("checked", "checked");
jQuery("body").removeClass("miniFont MaxFont").addClass("midFont");
}
else if (fontCode == 'maxFont'){
jQuery('#maxFont').attr("checked", "checked");
jQuery("body").removeClass("miniFont midFont").addClass("MaxFont");
}
else{}

localStorage.setItem("fontCode", fontCode); 
});

if (localStorage.getItem("fontCode") !== null) {
var fontCode = localStorage.getItem("fontCode");
if (fontCode == 'miniFont'){
jQuery('#radio-1-1').attr("checked", "checked");
jQuery("body").removeClass("midFont MaxFont").addClass("miniFont");
}
else if (fontCode == 'midFont'){
jQuery('#radio-1-2').attr("checked", "checked");
jQuery("body").removeClass("miniFont MaxFont").addClass("midFont");
}
else if (fontCode == 'maxFont'){
jQuery('#radio-1-3').attr("checked", "checked");
jQuery("body").removeClass("miniFont midFont").addClass("MaxFont");
}
else{}
}
}

CSS

.radioFontHolders{
border:0px #e1e1e1 solid;
padding:10px 5px 10px 5px;
margin-top:30px;width:100%;
}
.letterFontsHolder{
padding:1px;width:170px;
}
.miniLetter, .midLetter, .bigLetter{
float:left;font-family:"Times New Roman", Times, serif;
font-weight: 700;height:32px;
border-bottom:1px #ccc solid;
color:#035183
}
.miniLetter{
width:33.33333%;
font-size:18px;
width:40px;line-height:41px;
padding-left:7px;
}
.midLetter{
width:33.33333%;
font-size:26px;width:50px;line-height:36px;
padding-left:7px;
}
.bigLetter{
width:33.33333%;
font-size:40px;width:60px;line-height:26px;
}
.font-1, .font-2, .font-3{
width:28px;float:left;height:20px;
}
/* set the fonts */
.miniFont{font-size:0.9em}
.midFont{font-size:1.3em}
.MaxFont{font-size:1.5em}
.radioHolders{
margin-top:10px;
margin-bottom:10px;
z-index: 1;width: 200px;
z-index:999;background-color: transparent
}
/* radios */
.regular-radio{display: none}
.regular-radio + label {
margin-left:10px;
-webkit-appearance: none;
background-color: #fafafa;
border: 1px solid #cacece;
box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05);
padding: 9px;
border-radius: 50px;
display: inline-block;
position: relative;
background-image: -webkit-linear-gradient(hsla(0,0%,100%,.1), hsla(0,0%,0%,.1));
border-radius: 100%;
zoom: 1; cursor: pointer;
display: inline-block;
margin-right: 12px;
-webkit-appearance: none;
}
.regular-radio:nth-child(1) + label:after{background-color:#CDCDCD}
.regular-radio:nth-child(3) + label:after{background-color:#CDCDCD}
.regular-radio + label:after{background-color:#CDCDCD}
/* selected */
.regular-radio:checked + label:after {
content: ' ';
width: 12px;
height: 12px;
border-radius: 50px;
position: absolute;
top: 3px;
background: #84B942;
box-shadow: inset 0px 0px 10px rgba(0,0,0,0.3);
text-shadow: 0px;
left: 3px;
font-size: 32px;
border-radius: 100%;
box-shadow: inset 0 0 0 1px hsla(0,0%,0%,.4), 0 1px 1px hsla(0,0%,100%,.8);
content: '';
display: block;
}
/* not selected */
.regular-radio + label:after {
content: ' ';
width: 12px;
height: 12px;
border-radius: 50px;
position: absolute;
top: 3px;
box-shadow: inset 0px 0px 10px rgba(0,0,0,0.3);
text-shadow: 0px;
left: 3px;
border-radius: 100%;
box-shadow: inset 0 0 0 1px hsla(0,0%,0%,.4), 0 1px 1px hsla(0,0%,100%,.8);
content: '';
display: block;
}

Thanks, Christian

Add a breadcrumb in SharePoint 2013 — February 28, 2015

Add a breadcrumb in SharePoint 2013

Hi! Here come’s just a short blog about how to implement a breadcrumb in SharePoint 2013 onprem or online, something that can be just as useful like the other navigation elements like the global navigation.

The user needs to know his location in the website’s hierarchical structure in order to possibly browse back to a higher level in the site hierarchy, useful when the structure of the SharePoint site follows a strict hierarchical structure of similar formatted content e.g not a search driven structure by manage metadata. Note that a breadcrumb should not be used on the startpage of your site collection, you can hide it on the welcome page with a display none in the page layout or similar. That’s cool, but how about to implement this breadcrumb then, well it’s just to add a ASP:SiteMapPath control onto your custom masterpage!

breadcrumb

Let’s try this!

Add this somewhere in the markup of your Custom master page

<div class="customBreadCrumb ms-dialogHidden">
   <asp:SiteMapPath SiteMapProvider="CurrentNavigation" ID="ContentMap" SkipLinkText="" RenderCurrentNodeAsLink="false" NodeStyle-CssClass="ms-sitemapdirectional" runat="server"/>
</div>

And here’s the CSS, note that I’ve created the Arrows with CSS3 with a little help of on of my favorites in CSS3; transform (rotate, scale and skew)

.customBreadCrumb{
padding-left:10px;
padding-right:10px;
padding-bottom:0px;
}
.customBreadCrumb > span{
background-color:transparent;
border-bottom:0px #ccc solid
}
.customBreadCrumb a:link, .customBreadCrumb a:visited {
color:#555;
font-family:Arial;
font-size: 12px
}   
.customBreadCrumb .ms-sitemapdirectional{
font-family:Arial;
font-size: 12px;
color:#999
}
/* hide separators */
#ctl00_ContentMap span:nth-of-type(2), #ctl00_ContentMap span:nth-of-type(4), #ctl00_ContentMap span:nth-of-type(6), #ctl00_ContentMap span:nth-of-type(8) {
display:none
}
.customBreadCrumb {
position:relative;
padding:10px 0px 0px 8px
}
#ctl00_ContentMap  {
display: inline-block;
border: 1px solid #E8DABF;
border-radius: 5px;
overflow: hidden;
width: 100%;
}
#ctl00_ContentMap span, .customBreadCrumb a:link, .customBreadCrumb a:visited{
font-family:Arial;
}
/* change height? change both line height and height and width for the ID #ctl00_ContentMap span:after*/
#ctl00_ContentMap span, #ctl00_ContentMap span:after{
line-height: 30px;
height: 30px
}
#ctl00_ContentMap span:after {
width: 35px;
content: '';
z-index: 1;
border-right: 1px solid #E8DABF;
border-top: 1px solid #E8DABF;
position: absolute;
right: 0;
top: 0;
box-sizing: border-box;
-webkit-transform: translateX(20px) rotate(45deg) scale(0.6) skew(15deg,15deg);
transform: translateX(20px) rotate(45deg) scale(0.6) skew(15deg,15deg);
-ms-transform: translateX(20px) rotate(45deg) scale(0.6) skew(15deg,15deg); /* IE9 */
}
#ctl00_ContentMap span {
list-style: none;
float: left;
display: block;
position: relative;
padding: 0px 14px;
text-align: center;
}
#ctl00_ContentMap span a {
padding:0px 6px 0px 12px;
color: #000;
text-decoration: none;
}
#ctl00_ContentMap span:last-child {
padding-left: 20px;
}
.ms-sitemapdirectional a{
font-family:Arial;
font-size:1.0em;
}
#ctl00_ContentMap span:first-child {
padding-left: 0px;
}
#ctl00_ContentMap span,
#ctl00_ContentMap span:after{
background-color:#fff;
}
#ctl00_ContentMap{
border:1px;border-radius: 2px;
}
#ctl00_ContentMap > span{
margin-bottom:1px;
}
#ctl00_ContentMap span a:hover{
color: green;text-decoration: underline;
}
#ctl00_ContentMap span:first-child{}
#ctl00_ContentMap span:after {
width: 35px;
-webkit-transform: translateX(20px) rotate(45deg) scale(0.5) skew(15deg,15deg);
transform: translateX(20px) rotate(45deg) scale(0.5) skew(15deg,15deg);
-ms-transform: translateX(20px) rotate(45deg) scale(0.5) skew(15deg,15deg);
}
.ms-sitemapdirectional a{}
.customBreadCrumb a:link, .customBreadCrumb a:visited{
color:#555;
}   
.customBreadCrumb .ms-sitemapdirectional{}
#ctl00_ContentMap span:last-child{
overflow:hidden
}

/ Christian

What’s up 2015 — January 31, 2015

What’s up 2015

Ok readers, so it was time to sum up the past year and take a look into what to expect in this new year. This year will be a kind of change in my career, from February 1. The big news is that I will start up my own company, ‘eVolution Interactive Sthlm’ after working as a SharePoint consultant at two different consulting companies since 2006, Humandata and CGI. Of course it is just incredibly exciting and I will then hopefully be able to take me a little more time to work on community around SharePoint, anyway, I will not slowing down any way when it comes to writing blog posts, other articles and speaking at conferences, etc.

At the moment, I have not yet fixed any public website with a description of what services I can help with, contact information, etc., for those who are interested in hiring me, but as soon as I have it in place, I will publish a link on this blog!

Plans for the future

Well the details will change constantly and nobody knows the future, but I will do my best and work as hard as I can to get my business to go around. Right now I’m looking for an office space, need to find an inspiring place somewhere in central Stockholm, I have a few options I’m considering at the moment so we’ll see what happens here.

I will as before continue doing what I love most about, consulting and educate. I will publish some apps, continue to write blog posts and speak at SharePoint conferences both in Sweden and internationally.

2014

A fun year at full speed, two major challenging projects on SharePoint 2013 in which I participated as a front-end developer and web designer. Besides all this, I have also taken the certification ‘70-480 Programming in HTML5 with JavaScript and CSS3’ this summer, which actually was quite a challenging one I must say. Yes that’s right, I also work as a teacher at LabCenter in Stockholm and at EC. I do educate in the area of SharePoint branding, apps and client code scripting etc. The education part of my job is exciting and will definitely have to continue this year as well. I’m also members of the management team for EC.

Besides all this, I have traveled a lot and talked at a few different SharePoint Conferences around like Miami and Las Vegas SharePoint Conference 2014, Dubai SP Saturday, Slovenia SharePoint Days 2014, Stockholm, SEF2014 and the yearly MVP Summit in Seattle. Every one of this conferences and experience in itself really deserves its own blog post. I have met and had exchanges of so many people, meet old friends and got new ones, people from different cultures and from different backgrounds, that part is perhaps what has given most in itself.

Some pictures from a few of the events the past year
coll1

coll2

coll3

coll4

coll5

coll6

SharePoint Server MVP 2014 — April 30, 2014

SharePoint Server MVP 2014

I’m very happy to announce that I’ve been renewed with the award SharePoint MVP 2014 by Microsoft for the fourth time in a row!

MVP2014

To receive this award again makes me really proud and of course motivates me to keep on writing articles, speaking at conferences and participate in different projects for the community around SharePoint. Many thanks to Microsoft, my MVP lead, colleagues, friends, readers of this blog and all great people out there in the world wide SharePoint community. If you want to know more about the program, read it from the Microsoft MVP site.

Just as Before, you can count on more posts about SharePoint branding and front end development in general. Recently, I have written a blog series about how to customizing SharePoint 2013 global navigation and next up I planning to write a couple of blogs about REST in SharePoint 2013. I think I’ll write this in the APP perspective using NAPA or VS2013. If you got some ideas here regarding the content, just drop a comment.

Furthermore, maybe we will meet on any SharePoint Conference this year>, the next opportunity will be at SharePoint Saturday in Dubai May 17 where I’ll be speaking about SharePoint Branding.

See you around!

/ Christian

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 5 — March 31, 2014

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 5

Time for the last post in the series about how to customize the global navigation in SharePoint 2013. In this post, you get two new examples of how you can customize the navigation with the help of CSS. This will work for SharePoint 2013, Online or Onprem when using structural navigation.

Nav-Red

Add a nav tag in the master page

I added a nav tag as a container for the SharePoint top menu control. The nav tag is a new tag in HTML 5 and the element should be used for major navigation blocks in the html file. It’s a semantic tag that tells the browser or other reading software such as a search engine that it’s a navigation, compared to a div that just don’t say anything about its content. The CSS is dependent on this nav tag, so if you want to cut & paste, you need to add the nav tag in the master.

<nav>
<SharePoint:AjaxDelta id="DeltaTopNavigation" BlockElement="true" CssClass="ms-displayInline ms-core-navigation" role="navigation" runat="server">
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate">
<Template_Controls>
<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="SPNavigationProvider"
id="topSiteMap"	runat="server" StartingNodeUrl="sid:1002"/>
</Template_Controls>
</SharePoint:DelegateControl>
<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server">
<SharePoint:AspMenu ID="TopNavigationMenu"
Runat="server" EnableViewState="false" DataSourceID="topSiteMap"
AccessKey="<%$Resources:wss,navigation_accesskey%>"
UseSimpleRendering="true" UseSeparateCss="false"
Orientation="Horizontal"
StaticDisplayLevels="2" AdjustForShowStartingNode="true"
MaximumDynamicDisplayLevels="2"	SkipLinkText="" />
</asp:ContentPlaceHolder>
</SharePoint:AjaxDelta>			
</nav>

CSS for the red navigation

In this first example, I use the CSS:after selector to get an arrow and set it’s position relative to it’s parent element, in this I can set the arrow to a selected element with out the use of a image.

#pageTitle{
display:none
}
nav ul li {
background:#dd4433;
border-left: 1px solid #c73d2e;
text-align: center;
height:55px;
}
nav ul li a {
font:16px/36px Arial, Helvetica, sans-serif;
color: #fff;
width:140px;
height:46px;
}
nav{margin:5px auto}
nav ul.root > li.static > ul.static{
border-left:1px #ee4e3d solid;
}
nav .ms-core-navigation .ms-core-listMenu-horizontalBox li.static >  .ms-core-listMenu-item{
margin-right:10px;
padding-top:7px;
margin:0px 0px 0px 0px
}
nav .ms-core-navigation .ms-core-listMenu-item, nav .ms-core-navigation .ms-core-listMenu-item:link, nav .ms-core-navigation .ms-core-listMenu-item:visited{
color:#fff;
}
nav .ms-core-navigation .ms-core-listMenu-horizontalBox ul.static > li.selected > a > span > span{color:#fff}
nav ul li a:hover{color:#000}
nav li{border-right:1px solid #ee4e3d}
nav li:last-child{border-right:0px solid #ee4e3d}
nav li.selected:after{
content:'';
position:relative;
width:0px;
display:block;
left:60px;
border:10px solid transparent;
border-top:8px solid #d43;
}

CSS for the blue navigation

For this blue navigation I use a smooth CSS gradient and a portion of border radius to get the rounded corners. If you want to adjust the width to be stretched relative to it’s content, you can use the out commented paddings instead of the fixed width if you prefer.

Nav-Blue

nav {
overflow:hidden
}
#pageTitle{
display:none
}
nav ul li {
background: #618ba4; /* Old browsers */
background: -moz-linear-gradient(top, #618ba4 0%, #406a82 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#618ba4), color-stop(100%,#406a82)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #618ba4 0%,#406a82 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #618ba4 0%,#406a82 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #618ba4 0%,#406a82 100%); /* IE10+ */
background: linear-gradient(to bottom, #618ba4 0%,#406a82 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#618ba4', endColorstr='#406a82',GradientType=0 ); /* IE6-9 */
border-left: 1px solid #7395a8;
border-right: 1px solid #406275;
text-align: center;
height:55px;
}
nav ul li a {
font:16px/36px Arial, Helvetica, sans-serif;
color: #fff;
width:140px;
height:46px;
/*padding-right:20px;padding-left:20px*/
}
nav ul li:last-child {
border-right: none;
border-radius: 0px 5px 5px 0px;
-moz-border-radius: 0px 5px 5px 0px;
-webkit-border-radius: 0px 5px 5px 0px;
}
nav {
margin:1px auto;
border-radius:5px;
}
nav ul.root > li.static > ul.static{
border-left:1px #406a82 solid;
}
nav div > div > ul.static > li.static a:hover{
background: #406a82;
height:46px;
}
nav div > div > ul.static > li.static > ul.static > li:hover {
background: #406a82;
}
nav div > ul.root > li.selected a:hover {
background: #406a82!important;
height:55px;
}
nav .ms-core-navigation .ms-core-listMenu-horizontalBox li.static >  .ms-core-listMenu-item{
margin-right:10px;
padding-top:7px;
margin:0px 0px 0px 0px
}
nav .ms-core-navigation .ms-core-listMenu-item, nav .ms-core-navigation .ms-core-listMenu-item:link, nav .ms-core-navigation .ms-core-listMenu-item:visited{
color:#fff;
}
nav .ms-core-navigation .ms-core-listMenu-horizontalBox ul.static > li.selected > a > span > span{
color: #fff;
}

Take a look at the previous posts here:

I hope you had joy of this posts in the series! Please drop a comment if you have any question.

/ Christian

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 4 — February 22, 2014

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 4

Just as in the previous post, here you got some more examples about how you can spice up the global navigation by add some CSS3. In this post I have included five different kind of link effects animations for you to try out. I’ve used tympanus great piece of work ‘Subtle and modern effects for links or menu items’ tympanus.net/Development/CreativeLinkEffects/ and slightly modified this to work with the markup and CSS of SharePoint 2013.

This is an example of how you can work with CSS3 2D transform methods like translate and scale on pseudo elements (before and after). Take a look at my video on you tube to see this five examples in action!

GlobalNav2013tympanus

Let’s start

You need to add a nav tag in your custom master and some CSS in your exteral CSS file, linked from the master page file. You can change the class name for the nav element to one of this five examples, the available numbers are 1,4,7,12 or 19. For example change cl-effect-1 to cl-effect-4 etc. You can download all the CSS and the navigation control here as well.

Add a nav tag in the master page

I added a nav tag as a container for the SharePoint top menu control. The nav tag is a new tag in HTML 5 and the element should be used for major navigation blocks in the html file. It’s a semantic tag that tells the browser or other reading software such as a search engine that it’s a navigation, compared to a div that just don’t say anything about its content.

<nav class="cl-effect-1">

<SharePoint:AjaxDelta id="DeltaTopNavigation" BlockElement="true" CssClass="ms-displayInline ms-core-navigation" role="navigation" runat="server">
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate">
<Template_Controls>
<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="SPNavigationProvider"
id="topSiteMap" runat="server" StartingNodeUrl="sid:1002"/>
</Template_Controls>
</SharePoint:DelegateControl>
<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server">
<SharePoint:AspMenu ID="TopNavigationMenu"
Runat="server" EnableViewState="false" DataSourceID="topSiteMap"
AccessKey="<%$Resources:wss,navigation_accesskey%>"
UseSimpleRendering="true" UseSeparateCss="false"
Orientation="Horizontal"
StaticDisplayLevels="2" AdjustForShowStartingNode="true"
MaximumDynamicDisplayLevels="2" SkipLinkText="" />
</asp:ContentPlaceHolder>
</SharePoint:AjaxDelta>
			
</nav>

And the CSS

/* ---------- NAVIGATION ---------- */
#pageTitle{display:none!important}
/* general */
nav a {
position: relative;
display: inline-block;
margin: 15px 25px;
outline: none;
color: #fff;
text-decoration: none;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 400;
text-shadow: 0 0 1px rgba(255,255,255,0.3);
font-size: 1.35em;
}
nav a:hover,
nav a:focus {
outline: none;
}
/* effect type */
/* Effect 1: Brackets */
.cl-effect-1 a::before,
.cl-effect-1 a::after {
display: inline-block;
opacity: 0;
-webkit-transition: -webkit-transform 0.3s, opacity 0.2s;
-moz-transition: -moz-transform 0.3s, opacity 0.2s;
transition: transform 0.3s, opacity 0.2s;
font-weight: 900;
font-size:25px
}
.cl-effect-1 a::before {
margin-right: 10px;
content: '[';
-webkit-transform: translateX(20px);
-moz-transform: translateX(20px);
transform: translateX(20px);
}
.cl-effect-1 a::after {
margin-left: 10px;
content: ']';
-webkit-transform: translateX(-20px);
-moz-transform: translateX(-20px);
transform: translateX(-20px);
}
.cl-effect-1 a:hover::before,
.cl-effect-1 a:hover::after,
.cl-effect-1 a:focus::before,
.cl-effect-1 a:focus::after {
opacity: 1;
-webkit-transform: translateX(0px);
-moz-transform: translateX(0px);
transform: translateX(0px);
}
/* Effect 4: bottom border enlarge */
.cl-effect-4 a {
padding: 0 0 10px;
}
.cl-effect-4 a::after {
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 1px;
background: #0072C6;
content: '';
opacity: 0;
-webkit-transition: height 0.3s, opacity 0.3s, -webkit-transform 0.3s;
-moz-transition: height 0.3s, opacity 0.3s, -moz-transform 0.3s;
transition: height 0.3s, opacity 0.3s, transform 0.3s;
-webkit-transform: translateY(-10px);
-moz-transform: translateY(-10px);
transform: translateY(-10px);
}
.cl-effect-4 a:hover::after,
.cl-effect-4 a:focus::after {
height: 5px;
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
transform: translateY(0px);
}
/* Effect 7: second border slides up */
.cl-effect-7 a {
padding: 12px 10px 10px;
color: #566473;
text-shadow: none;
font-weight: 700;
}
.cl-effect-7 a::before,
.cl-effect-7 a::after {
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 3px;
background: #566473;
content: '';
-webkit-transition: -webkit-transform 0.3s;
-moz-transition: -moz-transform 0.3s;
transition: transform 0.3s;
-webkit-transform: scale(0.85);
-moz-transform: scale(0.85);
transform: scale(0.85);
}
.cl-effect-7 a::after {
opacity: 0;
-webkit-transition: top 0.3s, opacity 0.3s, -webkit-transform 0.3s;
-moz-transition: top 0.3s, opacity 0.3s, -moz-transform 0.3s;
transition: top 0.3s, opacity 0.3s, transform 0.3s;
}
.cl-effect-7 a:hover::before,
.cl-effect-7 a:hover::after,
.cl-effect-7 a:focus::before,
.cl-effect-7 a:focus::after {
-webkit-transform: scale(1);
-moz-transform: scale(1);
transform: scale(1);
}
.cl-effect-7 a:hover::after,
.cl-effect-7 a:focus::after {
top: 0%;
opacity: 1;
}
/* Effect 12: circle */
.cl-effect-12 a::before,
.cl-effect-12 a::after {
position: absolute;
top: 50%;
left: 50%;
width: 70px;
height: 70px;
border: 2px solid rgba(0,0,0,0.1);
border-radius: 50%;
content: '';
opacity: 0;
-webkit-transition: -webkit-transform 0.3s, opacity 0.3s;
-moz-transition: -moz-transform 0.3s, opacity 0.3s;
transition: transform 0.3s, opacity 0.3s;
-webkit-transform: translateX(-50%) translateY(-50%) scale(0.2);
-moz-transform: translateX(-50%) translateY(-50%) scale(0.2);
transform: translateX(-50%) translateY(-50%) scale(0.2);
}
.cl-effect-12 a:hover::before,
.cl-effect-12 a:hover::after,
.cl-effect-12 a:focus::before,
.cl-effect-12 a:focus::after {
opacity: 1;
-webkit-transform: translateX(-50%) translateY(-50%) scale(1);
-moz-transform: translateX(-50%) translateY(-50%) scale(1);
transform: translateX(-50%) translateY(-50%) scale(1);
}
/* Effect 18: cross */
.cl-effect-18 {
position: relative;
z-index: 1;
}
.cl-effect-18 a {
padding: 0 5px;
color: #b4770d;
font-weight: 700;
-webkit-transition: color 0.3s;
-moz-transition: color 0.3s;
transition: color 0.3s;
}
.cl-effect-18 a::before,
.cl-effect-18 a::after {
position: absolute;
width: 100%;
left: 0;
top: 50%;
height: 2px;
margin-top: -1px;
background: #0072C6;
content: '';
z-index: -1;
-webkit-transition: -webkit-transform 0.3s, opacity 0.3s;
-moz-transition: -moz-transform 0.3s, opacity 0.3s;
transition: transform 0.3s, opacity 0.3s;
pointer-events: none;
}
.cl-effect-18 a::before {
-webkit-transform: translateY(-20px);
-moz-transform: translateY(-20px);
transform: translateY(-20px);
}
.cl-effect-18 a::after {
-webkit-transform: translateY(20px);
-moz-transform: translateY(20px);
transform: translateY(20px);
}
.cl-effect-18 a:hover,
.cl-effect-18 a:focus {
color: #fff;
}
.cl-effect-18 a:hover::before,
.cl-effect-18 a:hover::after,
.cl-effect-18 a:focus::before,
.cl-effect-18 a:focus::after {
opacity: 0.7;
}
.cl-effect-18 a:hover::before,
.cl-effect-18 a:focus::before {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
.cl-effect-18 a:hover::after,
.cl-effect-18 a:focus::after {
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-45deg);
}
/* Effect 19: cross */
.cl-effect-19 {
position: relative;
z-index: 1;
}
.cl-effect-19 a {
padding: 0 5px;
color: #b4770d;
font-weight: 700;
-webkit-transition: color 0.3s;
-moz-transition: color 0.3s;
transition: color 0.3s;
}
.cl-effect-19 a::before,
.cl-effect-19 a::after {
position: absolute;
width: 100%;
left: 0;
top: 50%;
height: 2px;
margin-top: -1px;
background: #0072C6;
content: '';
z-index: -1;
-webkit-transition: -webkit-transform 0.3s, opacity 0.3s;
-moz-transition: -moz-transform 0.3s, opacity 0.3s;
transition: transform 0.3s, opacity 0.3s;
pointer-events: none;
}
.cl-effect-19 a::before {
-webkit-transform: translateY(-20px);
-moz-transform: translateY(-20px);
transform: translateY(-15px);
}
.cl-effect-19 a::after {
-webkit-transform: translateY(20px);
-moz-transform: translateY(20px);
transform: translateY(15px);
}
.cl-effect-19 a:hover,
.cl-effect-19 a:focus {
color: #fff;
}
.cl-effect-19 a:hover::before,
.cl-effect-19 a:hover::after,
.cl-effect-19 a:focus::before,
.cl-effect-19 a:focus::after {
opacity: 0.7;
}
.cl-effect-19 a:hover::before,
.cl-effect-19 a:focus::before {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(90deg);	
}
.cl-effect-19 a:hover::after,
.cl-effect-19 a:focus::after {
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
transform: rotate(-90deg);	
}

I hope you had joy of this and please drop a comment if you have any question!

/ Christian

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 3 — January 31, 2014

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 3

In this third post, I will show how you can spice up the global navigation by add some CSS3. If you ever wanted to add some of the new CSS3 attributes like box-shadow or transitions to make some cool effects like animations this is a post for you. Now let’s change the look & feel for the global navigation in SharePoint Server to your heart’s desire!

GlobalNavIII

This example is suitable for SharePoint Server onprem as well as for SharePoint Online. The navigation is built after a structured navigation, there’s no CSS to handle dropdowns. The following CSS code includes transitions, an animation effect that let an element gradually change from one style to another. With this technique you can give the navigation an extra layer of interactivity.

There’s a bunch of sites out there like CSS Deck, CSS-trick, SpeckyBoy, Smashing Magazine etc. where you can find snippets and tutorial to get going with the latest stuff on HTML 5 and CSS 3. Why not find an example and try to implement this in SharePoint. In this post I’ll show you how to take one of this example and modify this a bit to fit it into SharePoint’s markup. Take a look at this example: http://cssdeck.com/labs/large-pressable-css3-navigation now let’s implement this one!

First of all, let’s wrap the SharePoint:AspMenu with a nav tag. Open your custom master and just add this two lines, start and end using the new HTML5 tag (nav) or an old good div if you prefer.

<SharePoint:AjaxDelta id="DeltaTopNavigation" BlockElement="true" CssClass="ms-displayInline ms-core-navigation" role="navigation" runat="server">
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate">
<Template_Controls>
<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="SPNavigationProvider" id="topSiteMap" runat="server" StartingNodeUrl="sid:1002"/>
</Template_Controls>
</SharePoint:DelegateControl>
<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server">
<nav id="nav">
<SharePoint:AspMenu ID="TopNavigationMenu" Runat="server" EnableViewState="false" DataSourceID="topSiteMap" AccessKey="<%$Resources:wss,navigation_accesskey%>" UseSimpleRendering="true" UseSeparateCss="false" Orientation="Horizontal" StaticDisplayLevels="2" AdjustForShowStartingNode="true" MaximumDynamicDisplayLevels="2" SkipLinkText="" />
</nav>
</asp:ContentPlaceHolder>
</SharePoint:AjaxDelta>

And at last it’s time for the CSS:

.ms-core-navigation .ms-core-listMenu-horizontalBox li.static >  .ms-core-listMenu-item{
margin-right:1px
}
.ms-core-navigation .ms-core-listMenu-horizontalBox ul.static > li.selected > a > span > span{
color:#CFE1F1
}
#pageTitle{
display:none
}
#nav {
margin:4px auto;
overflow:hidden;
opacity:0.90;
border-radius:5px;
list-style-type:none;
}
#nav ul {
background-color:#2C4A70;
padding:0px 0px 1px 0px;
border-radius:5px;
}
#nav ul li {
height:55px;
}
#nav ul li a {
font:21px/52px Arial, Helvetica, sans-serif;
background-color: #0f6fb2;
background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(15, 111, 178)), to(rgb(34, 65, 112)));
background-image: -webkit-linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
background-image: -moz-linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
background-image: -o-linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
background-image: -ms-linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
background-image: linear-gradient(top, rgb(15, 111, 178), rgb(34, 65, 112));
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#0f6fb2', EndColorStr='#224170');
color: #fff;
text-decoration: none;
box-shadow:inset 0 1px 0 #0081bd,inset 0 2px 0 #0078b0,inset 0 3px 0 #0070a3, 0 0 10px rgba(0,0,0,0.2);
box-sizing:border-box;
transition:all .2s ease-in;
-o-transition:all .2s ease-in;
-moz-transition:all .2s ease-in;
-webkit-transition:all .2s ease-in;
}
#nav ul li a {width: 140px}
#nav ul li:first-child a {
-webkit-border-top-left-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-bottomleft: 5px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
#nav ul li:last-child a {
-webkit-border-top-right-radius: 5px;
-webkit-border-bottom-right-radius: 5px;
-moz-border-radius-topright: 5px;
-moz-border-radius-bottomright: 5px;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}#nav ul li a:hover {
box-shadow:inset 0 1px 0 #0070a3,inset 0 0 30px 0 #142a4a;
text-shadow:0 1px 3px #143157;
border-bottom:5px solid #0e223d;
}
#nav ul li a span {
border-left:1px solid #143157;
border-right:1px solid #1563a3;
height:100%;
display:block;
text-align:center;
box-sizing:border-box;
}
#nav ul li:first-child a span { border-left: none}
#nav ul li:last-child a span { border-right: none}

Please drop a comment if you have any questions

/ Christian

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 2 — December 31, 2013

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 2

In this second post, I will show how you can create your own markup for the global navigation. This could be a great option when you need to take advantage of HTML 5 tags and additional jQuery plugins that requires simpler markup than SharePoint gives you out of the box.
Alternative to create a complete new control via code, an easy way is to use a standard old good .NET repeater control, instead of the SharePoint:AspMenu control and let the repeater connect to a asp:SiteMapDataSource. To use a repeater control instead of the SharPoint:AspMenu is most likely something suitable for a public SharePoint site.

simple
The repeater gives you a possibility to simplify the markup and just render a minimum of UL and Lis where you can set you own names for IDs or classes.
In order to add a selected class for selected links in the navigation you’ll need to use code behind or java script to do this. The thing here is that JS this will be valid as long as the page is still open, as soon as the user goes to a new page the JS will be reset. To overcome this you can use a cookie or read the URL, parse it, and then add a selected class to the current navigation node or as in this solution just use jQuery with location.pathname to compare the selected link to what’s in the URL.

Ok, if you only need a plain navigation without any dropdown items, replace the old control with this stuff:

<SharePoint:AjaxDelta id="DeltaTopNavigation" BlockElement="true" CssClass="ms-displayInline ms-core-navigation" role="navigation" runat="server">
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate"></SharePoint:DelegateControl>
<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server">
<nav class="SpNav">
<ul id="SpNavUL">
<asp:Repeater ID="GlobalNavMenuItems" runat="server" DataSourceID="topSiteMap">
<ItemTemplate>
<li>
<asp:HyperLink ID="SpNavLinks" runat="server" NavigateUrl='<%# Eval("Url")%>' Text='<%# Eval("Title") %>'></asp:HyperLink>
</li>
</ItemTemplate>
</asp:Repeater>
<asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="CombinedNavSiteMapProvider" id="topSiteMap" runat="server" StartingNodeUrl="sid:1002" />
</ul>
</nav>	 
</asp:ContentPlaceHolder>
</SharePoint:AjaxDelta>

And the CSS:

#SpNavUL, #SpNavUL ul {
margin:0;padding:0;list-style:none;
}
#SpNavUL{
margin: 0px auto;
border: 1px solid #222;
background-color: #111;
background-image: linear-gradient(#444, #111);
border-radius: 6px;
box-shadow: 0 1px 1px #777;
}
#SpNavUL:before,
#SpNavUL:after {
content: "";
display: table;
}
#SpNavUL:after {
clear: both;
}
#SpNavUL li {
float: left;
border-right: 1px solid #222;
box-shadow: 1px 0 0 #444;
position: relative;
}
#SpNavUL a {
float: left;
padding: 12px 30px;
color: #999;
text-transform: uppercase;
font: bold 12px Arial, Helvetica;
text-decoration: none;
}
#SpNavUL li:hover > a {
color: #fafafa;
}
.SpNavActive{
color:#04acec!important;
}

And the jQuery:

$(document).ready(function(){
$(function() {
$('#SpNavUL a[href^="/' + location.pathname.split("/")[1] + '"]').addClass('SpNavActive');
});    
});

If you need to display dropdown items in the repeater control you have to use a bit server side script in the repeater to get the child nodes. You need to enable code blocks via web config file to get this working and if you need to do this for a production environment, don’t forget to handle the changes for the web.config in a WSP. Note that you will not be able to modify the web.config file for a SharePoint Online site.

double

Download all the stuff here including how to do with a repeater that includes a drop down menu.

Stay in tune for the next post in this series about the global navigation in SharePoint 2013

Please drop a comment if you have any question or just ideas for the next posts!

/ Christian

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 1 — November 30, 2013

Customizing SharePoint 2013 global navigation with CSS and jQuery – Part 1

It’s time for another blog series and this posts will be centered around how to customize and brand the global navigation in SharePoint 2013 online or on prem. In November 2010, I published three post in this subject for SharePoint 2010, and so far this posts together have generated 165.000 views and 166 comments. These blog entries has become a great success, and I am of course happy to be in any help when you are about to modify the navigation.

Creating a nice looking global navigation is a great way to improve the look and feel of the SharePoint site. A design that is well built and attractive will increase the usability and simply make the users happy! This post is based on a structural navigation in SharePoint 2013 server, and the focus is on the CSS parts. Let’s start with an easy example of how you can add some styling for the global navigation in order to get tabs in the navigation like the image below.

2013-globalnav

Three years have elapsed since the last time, so what has happened since SharePoint 2010 in terms of the global navigation?

  • The rendering markup from the navigation controls with class names has changed slightly
  • SharePoint 2013 is by default CSS3 and HTML 5 friendly
  • New jQuery framework and jQuery plugins to be used
  • Managed navigation that allows us to define the navigation based by Manage metadata

The OOTB markup for the global navigation looks like this:

HTMLnav

It’s still a complex markup and a lot of classes to deal with but let’s start with an easy example just to get going. I have added comments to the classes so you should be able to change for example colors and paddings by your needs. I’ll publish more examples in the next post.

/* --- Global navigation --- */
#DeltaPlaceHolderMain{
margin-top:30px;
}
.ms-breadcrumb-top{
background-color:#f2f2f2;
}
.ms-core-navigation > div > ul.root > li.static a:link, ul.root > li.static a:visited{
font-family:Arial; font-size:16px
}
/* links */
.ms-core-navigation > div > ul.root{
padding-top:8px;
padding-left:8px
}
.ms-core-navigation > div > ul.root > li a{
border:1px #fff solid;
padding:15px 20px 22px 20px;
font-size:15px;
}
.ms-core-navigation .ms-core-listMenu-horizontalBox li.static >  .ms-core-listMenu-item{
margin-right:8px
}
/* links not selected */
.ms-core-navigation > div > ul.root > li.static a:link, ul.root > li.static a:visited{
color:#222
}
/* links selected */
.ms-core-navigation > div > ul.root > li.static > ul.static > li.selected a:link, ul.root > li.static > ul.static > li.selected a:visited{
color:#222;
background-color:#fff
}
/* home link selected */
.ms-core-navigation div.ms-core-listMenu-horizontalBox > ul.static > li.selected a.selected{
border:1px transparent solid;
background-color:#fff
}
/* home */
.ms-core-navigation > div > ul.root > li.static > ul.static{
margin-left:0px
}
/* Hover */
.ms-breadcrumb-top .ms-core-navigation ul.static > li a:hover{
border:1px transparent solid;color:#222;
background-color:#fff
}

The next post in this series will cover

  • More branding examples you can download and use in your SharePoint environment
  • Using a ASP repeater control with jQuery to render custom markup
  • How to use jQuery for various UI effects
  • Branding example for a managed navigation

Please drop a comment if you have any question or just ideas for the next posts!

/ Christian