Telerik blogs

A couple of versions ago, WebKit implemented their own vendor-specific property for the CSS3 appearance. It is called -khtml-appearance.

According to the specifications of the World Wide Web Consortium:

“CSS appearance sets 'appearance' to the specified value and the other properties to their appropriate system value.  'normal' resets 'appearance' to 'normal' and the others to 'inherit'. The 'appearance' property does not affect the specified or computed values of any other properties.”

A little bit of vague explanation, however it is not the point of my blog post. Using this WebKit feature in RadFormDecorator was crucial, and let us drop the listening to the poorly supported onpropertychange event in Apple Safari and Google Chrome.

Now the decoration of checkboxes and radio buttons relies entirely on CSS without a single line of JavaScript. The good news is that almost all of the new CSS code has gone in the base style sheet of the control, and users with custom skins will have to add only two selectors at the bottom of their skin style sheet without changing the rest of the CSS or the image sprites to make the skin compatible with the new approach.

To clarify our new approach I will explain the technique for decorating checkboxes below. The approach is similar with radio button controls.

Unlike the FireFox –moz-appearance, -khtml-appearance implements a none value (a real none, unlike in FireFox, that implements none as “default”), that removes the default system appearance of the control it is applied to.

This beautiful feature allowed us to make full use of pseudo classes and attribute selectors and gives the developers the power to do almost anything with CSS rather than with JavaScript.

For example:

input[type=”checkbox”]  
{  
    -khtml-appearance: none;  
    width20px;  
    height20px;  
    backgroundurl(‘CheckBoxSprite.png’) no-repeat center 0;  

 

 

 

 

This will render the regular checkbox with a custom image. It is important to mention that –khtml-appearance: none works almost like visibility: hidden, with the difference that the element it is applied to loses its dimensions, and this is why we had to explicitly set width and height to it, along with an image sprite with the respective coordinates for the normal state of the control.

This will render the regular checkbox with a custom image. It is important to mention that works almost like , with the difference that the element it is applied to loses its dimensions, and this is why we had to explicitly set width and height to it, along with an image sprite with the respective coordinates for the normal state of the control.

In order to style the checked state of the control, we simply use the :checked pseudo class with the same image sprite, only setting coordinates for the “checked” state image in the sprite:

input[type=”checkbox”]:checked  
{  
    background-position-y: -100px;   

 

 

 

 

To make things even more beautiful, we use the :hover pseudo class to toggle the images then the the mouse hovers the control. And again – we use the same image sprite:

To make things even more beautiful, we use the pseudo class to toggle the images then the the mouse hovers the control. And again – we use the same image sprite:
input[type=”checkbox”]:hover  
{  
    /* only background-position value here */ 


 

 

… And:

input[type=”checkbox”]:hover:checked  
{  
    /* only background-position value here */ 

Further, what we have to take care of is the disabled (both normal, checked and hover) states of the control. To target a disabled checkbox, we use the disabled HTML attribute as a selector. The standard approach to mark an element as disabled on the Web is to make it decrease its opacity, so:

input[type="checkbox"][disabled]  
{  
    opacity: .5;  

Note that unlike [type=”checkbox”], we do not set [disabled=”disabled”], but [disabled] only because there is only one value for this attribute - disabled.

For aesthetic purposes, in order to disable the hover effect on the disabled checkboxes, we add another two selectors for checked:disabled:hover and normal:disabled:hover to the existing normal state selector properties, as shown below:

input[type=”checkbox”],  
input[type=”checkbox”][disabled]:hover  
{  
    /* existing properties here */ 

… And:

input[type=”checkbox”]:hover,  
input[type="checkbox"][disabled]:hover:checked  
{  
    /* existing properties here */ 

Finally, as this approach is proprietary, we used a browser-specific hack – a @media query selector combined with a proprietary WebKit property (-webkit-min-device-pixel-ratio) that wraps the new selectors:

@media screen and (-webkit-min-device-pixel-ratio: 0)  
{  
    /* selectors for the CSS styling of checkboxes and radio buttons in Webkit */ 
    selector  
    {  
        property: value;   
    }  

This will ensure that our new rendering will not affect any other browser, but WebKit only.

Again, almost all of the new CSS is added to the base style sheet (Skins/FormDecorator.css). What is left now is to add references to the image sprites for radio buttons and checkboxes for the different skins in each skin style sheet (Skins/[SkinName]/FormDecorator.[SkinName].css). Again we shall use the WebKit hack. The new code should be added at the bottom of the style sheet.

@media screen and (-webkit-min-device-pixel-ratio: 0)  
{  
    /* checkboxes */ 
    .rfdCheckbox input[type="checkbox"],  
    .rfdCheckbox input[type="checkbox"][disabled]:hover  
    {  
        background-imageurl([SkinName]/FormDecorator/CheckBoxSprites.gif');  
    }  
 
    /* radio buttons */ 
    .rfdRadio input[type="radio"],  
    .rfdRadio input[type="radio"][disabled="disabled"]:hover  
    {  
        background-imageurl('[SkiName]/FormDecorator/RadioButtonSprites.png');  
    }  

 

Did you notice the .rfdCheckbox and .rfdRadio classes? In fact they are dummy classes, and are used only as pointers. They are set to the documentElement of the page or to the DecorationZoneID element when the DecoratedControls is “All”, “CheckBoxes” or “RadioButtons”. The idea is that if decoration of these is turned off, they do not get decorated, because the root element will not bear .rfdCheckbox or .rfdRadio.


About the Author

Iana Tsolova

is Product Manager at Telerik’s DevTools division. She joined the company back in the beginning of 2008 as a Support Officer and has since occupied various positions at Telerik, including Senior Support Officer, Team Lead at one of the ASP.NET AJAX teams and Technical Support Director. Iana’s main interests are web development, reading articles related to geography, wild nature and latest renewable energy technologies.

Comments

Comments are disabled in preview mode.