[SalesForce] How to style a checkbox in a Visualforce page using Lightning Design System

Preferably without using JavaScript.

This is my code using the SLDS, but the field value doesn't change or get set.

<div class="slds-form-element">
    <div class="slds-form-element__control">
        <span class="slds-checkbox">
            <apex:inputCheckbox html-name="options" id="divsup" html-checked="{!myobject.field__c}" value="{!myobject.field__c}"></apex:inputCheckbox>
            <label class="slds-checkbox__label" for="divsup">
                <span class="slds-checkbox--faux"></span>
                <span class="slds-form-element__label">Checkbox Label</span>
            </label>
        </span>
    </div>
</div>

Has anyone been able to style the checkbox correctly?

In this case I was trying to rerender a outputPanel when the checkbox changes, but I didn't post the actionsupport used (because I noticed that the checkbox wasn't even clickable anymore).

I want to be able to style a checkbox, and listen for changes so I can rerender a panel.

Best Answer

Sometimes you have to change the SLDS example to work correctly with Visualforce.

Visualforce depends on the input field having a specific "id" attribute, so the id of the checkbox is actually something like "j_id0:j_id2:divsup". This means the <label> element used by SLDS doesn't match your checkbox.

You have to use <apex:outputLabel> so Visualforce can match the ids of the label and the checkbox.

<div class="slds-form-element">
    <div class="slds-form-element__control">
        <span class="slds-checkbox">
            <apex:inputCheckbox html-name="options" id="divsup" html-checked="" value="{! isChecked}"></apex:inputCheckbox>
            <apex:outputLabel for="divsup" styleClass="slds-checkbox__label">
                <span class="slds-checkbox--faux"></span>
                <span class="slds-form-element__label">Checkbox Label</span>
            </apex:outputLabel>
        </span>
    </div>
</div>

Or if that doesn't work, you can fix-up these different ids when the page loads with this little bit of JavaScript.

var labels = document.querySelectorAll("input[type='checkbox'] + label");
for (var label of labels) {
    var checkbox = label.parentNode.querySelector("input");
    label.setAttribute("for", checkbox.id);
}