Salesforce Lightning Design system is implemented for Visualforce as a CSS library that you would include in your VF page as a static resource. In the same way you could include any other CSS library as a static resource, you can do the same with SLDS.
As such, there is absolutely no dependency between enabling Lightning Experience and using the raw design system CSS.
The Lightning Design System website gives some quickstarts on using it for Lightning Components, web pages (most likely running on Heroku), and Visualforce. Where it describes how to use it.
Alternatively, you could go get the Trailhead badge which also walks you though using it in a variety of contexts. There is a project, which focuses specifically on using SLDS with Visualforce.
* UPDATE *
Based on new features it seems worthwhile to mention some items that make the "problem" of Lightning and SLDS in Visualforce much easier.
To import the SLDS stylesheets manually into your Visualforce page today, you can now use the <apex:slds/>
tag in your Visualforce markup. To avoid clashes with the "classic" UI you probably would be best advised to also turn off those stylesheets.
And if you want your Visualforce pageBlock
markup to function both in Lightning and in Classic, as of Winter 18 (available very soon) release we have added a new apex:page
attribute called lightningstylesheets
. Here is a Visualforce page in Lightning:
In Classic:
And this is the code:
<apex:page lightningStylesheets="true" controller="DreamhouseProspects">
<apex:sectionHeader title="Leads" subtitle="Home"/>
<apex:form >
<apex:pageBlock >
<apex:pageBlockButtons location="top">
<apex:outputLabel value="Sort: " for="sortList" />
<apex:selectList value="{! sortOrder}" size="1" id="sortList">
<apex:selectOption itemvalue="LastName" />
<apex:selectOption itemvalue="FirstName" />
</apex:selectList>
<apex:commandButton value="Sort Table" action="{!sortList}" reRender="leads_list"/>
<apex:commandButton action="{!URLFOR($Action.Lead.New)}" value="New"/>
</apex:pageBlockButtons>
<apex:pageBlockTable value="{! leads }" var="ct" id="leads_list">
<apex:column headerValue="First Name">
<apex:outputLink value="/{! ct.Id}">{! ct.FirstName }</apex:outputLink>
</apex:column>
<apex:column value="{! ct.LastName }"/>
<apex:column value="{! ct.Email }"/>
<apex:column value="{! ct.Phone }"/>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>
The only things required to make this work are a page that makes use of the core pageBlock tags as the primary way that things are displayed and the use of the lightningStylesheets="true"
attribute in the apex:page
tag.
So here is my two cents
Note Per comments this does not seem to completely answer the question as OP is looking to keep classic look while providing a look that also appears well under Lightning using a single solution.
For VF components that you want to style as SLDS without having to modify the controller you need to de-componetize them. Adding styles after the DOM has been rendered as pointed out above is not great because it relies on implementation level details you have no control over. Not to mention it is just hacky...
Also, VF components just do a lot of the work for us. Unfortunately, with SLDS we are again going to need to do much of the HTML work ourselves but it is not really that bad.
Using a template approach like mentioned What is suggested approach to transfer VF pages to be lightning ready
So the idea for the code you posted would be to:
- Pageblocktable becomes an HTML table
- Use an apex repeat to build the table rows using the controller variable
- Use an input/output field with the appropriate slds styleclass in each table row
You can maintain controller and page functionality while doing this.
Bottom line is you will need to break these compound tags into HTML elements. Simple tags like input field can be used as is with the appropriate styleclass and surrounding HTML elements thus allowing you to keep built in functionality
Original Markup
<apex:page standardController="Contact" recordSetVar="cs">
<div class="slds cv">
<apex:form>
<apex:sectionHeader title="{!$ObjectType.Contact.labelPlural}" subtitle="All"/>
<apex:pageMessages />
<apex:pageBlock title="{!$ObjectType.Contact.labelPlural}">
<apex:pageBlockTable value="{!cs}" var="c">
<apex:column value="{!c.FirstName}"/>
<apex:column value="{!c.LastName}"/>
<apex:column value="{!c.Birthdate}"/>
<apex:column value="{!c.CreatedDate}"/>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</div>
</apex:page>
Output
SLDS Pageblock / Pageblocktable Markup
A bit more markup but the way it is done ensures that it continues working and does not rely on the "implementation level details" of the old VF components
<apex:page id="dummySLDSPage" standardController="Contact" recordSetVar="cs" showHeader="false"
standardStylesheets="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0">
<head>
<apex:stylesheet
value="{!URLFOR($Resource.SLDS, 'assets/styles/salesforce-lightning-design-system-vf.min.css')}"/>
</head>
<div class="SLDS">
<body>
<apex:form>
<apex:pageMessages/>
<!-- Replaces the Standard Pageblock Table Header-->
<div class="slds-page-header" role="banner" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<div class="slds-grid">
<div class="slds-col">
<div class="slds-media slds-no-space slds-grow">
<div class="slds-media__figure">
<svg aria-hidden="true" class="slds-icon slds-icon-standard-contact">
<use xlink:href="{!URLFOR($Resource.AppFrontier_Assets, '/assets/icons/standard-sprite/svg/symbols.svg#contact')}"></use>
</svg>
</div>
<div class="slds-media__body">
<p class="slds-text-title--caps slds-line-height--reset">{!$ObjectType.Contact.labelPlural}</p>
<p class="slds-page-header__title slds-truncate"
title="ALL">ALL</p>
</div>
</div>
</div>
</div>
</div>
<!-- Replaces the Pageblocktable Table -->
<table class="slds-table slds-table--bordered slds-table--cell-buffer">
<!-- Use a caption if desired
<caption class="slds-text-heading--label slds-p-bottom--medium">{!$ObjectType.Contact.labelPlural}</caption>
-->
<thead>
<tr class="slds-text-title--caps">
<th scope="col">
<div class="slds-truncate" title="{!$ObjectType.Contact.fields.FirstName.Label}">
{!$ObjectType.Contact.fields.FirstName.Label}
</div>
</th>
<th scope="col">
<div class="slds-truncate" title="{!$ObjectType.Contact.fields.LastName.Label}">
{!$ObjectType.Contact.fields.LastName.Label}
</div>
</th>
<th scope="col">
<div class="slds-truncate" title="{!$ObjectType.Contact.fields.BirthDate.Label}">
{!$ObjectType.Contact.fields.BirthDate.Label}
</div>
</th>
<th scope="col">
<div class="slds-truncate" title="{!$ObjectType.Contact.fields.CreatedDate.Label}">
{!$ObjectType.Contact.fields.CreatedDate.Label}
</div>
</th>
</tr>
</thead>
<tbody>
<apex:repeat value="{!cs}" var="c"> <!-- Build the columns -->
<tr>
<th scope="row" data-label="{!$ObjectType.Contact.fields.FirstName.Label}">
<div class="slds-truncate" title="{!c.FirstName}">
<apex:outputField value="{!c.FirstName}"/> <!-- Standard VF component -->
</div>
</th>
<td data-label="{!c.LastName}">
<div class="slds-truncate"
title="{!c.LastName}">
<apex:outputField value="{!c.LastName}"/>
</div>
</td>
<td data-label="{!c.Birthdate}">
<div class="slds-truncate"
title="{!c.Birthdate}">
<apex:outputField value="{!c.Birthdate}"/>
</div>
</td>
<td data-label="{!c.CreatedDate}">
<div class="slds-truncate"
title="{!c.CreatedDate}">
<apex:outputField value="{!c.CreatedDate}"/>
</div>
</td>
</tr>
</apex:repeat>
</tbody>
</table>
</apex:form>
</body>
</div>
</apex:page>
Output
The general idea would apply to the rest of the items you would like to convert. You could even go so far as spending a bit of time to make VF Components that are done in SLDS styling and used to replace existing VF components. If the project is large this could be beneficial as it would save a lot of time.
Maybe I should put a package of reusable replacement SLDS components for VF components together...hmm...There is already a library out there but it had way too much overhead and really hacked the styling.
Some additional resources:
VF SLDS Checkbox: SLDS and inputField checkbox
VF SLDS Lookup with autocomplete: Lookup Field Dual Keyboard Focus (Answered with working Autocomplete lookup component and JS example for VF/SLDS)
VF SLDS Select Checkboxes: Convert apex:selectCheckboxes into slds style
VF Page Messages Replacement: How to convert a Visualforce apex:pageMessages to be lightning style
Best Answer
WINTER-18 Update
new property for VF
<apex:page>
taglightningStyleSheets="[false|true]"
will supposedly be the single thing you need to do to convert VF pages to SLDS type styleshttps://releasenotes.docs.salesforce.com/en-us/winter18/release-notes/rn_vf_lightningstylesheets.htm
Previous Comments
Too much for a comment
This is the Template page I use for all VF pages now. It allows me to control the Navigation and add SLDS styling all starting from the same point:
Add in your own Error Message div to replace the standard page messages and use code to populate the message and go from there.
My VF pages now start like so: