Search code examples
jquery-uislickgridjquery-ui-theme

jQuery UI Theme Conflict: SlickGrid and jQuery UI Tabs


I'm trying to apply this SlickGrid example:

http://mleibman.github.com/SlickGrid/examples/example4-model.html

to my own web project.

When I drop my grid in to the top of my page, it renders correctly. However, when I drop it into a jQuery UI Tabs tab on the same page, the CSS Sprite that renders the search image is incorrectly offset.

The Problem

The icon is rendered with

<span title="Toggle search panel" class="ui-icon ui-icon-search ui-state-default ui-corner-all" style="float: right;" onclick="toggleFilterRow11()"/>

It looks like jQuery UI Tabs also uses the same CSS classes, and of course a conflict arises.

Looking at the effective styles in IE9, the control outside of jQuery UI Tabs that renders correctly has the following:

Correct styles

The control that renders incorrectly looks like this:

Wrong styles

Bottom Line

Placing the SlickGrid in a jQueryUI Tab causes the ui-icon-search class to be lost and therefore the wrong background-position-x/y to be set.

Why is that class being lost and how can I fix the issue?


Solution

  • The problem

    When jQueryUI creates tabs from the HTML it adds the jQueryUI CSS classes. From the jQueryUI examples:

    <div id="tabs">
        <ul>
            <li><a href="#tabs-1">Nunc tincidunt</a></li>
            <li><a href="#tabs-2">Proin dolor</a></li>
            <li><a href="#tabs-3">Aenean lacinia</a></li>
        </ul>
        <div id="tabs-1"></div>
        <div id="tabs-2"></div>
        <div id="tabs-3"></div>
    </div>
    

    becomes

    <div id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all">
        <ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
            <li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a href="#tabs-1">Nunc tincidunt</a></li>
            <li class="ui-state-default ui-corner-top"><a href="#tabs-2">Proin dolor</a></li>
            <li class="ui-state-default ui-corner-top"><a href="#tabs-3">Aenean lacinia</a></li>
        </ul>
        <div id="tabs-1" class="ui-tabs-panel ui-widget-content ui-corner-bottom"></div>
        <div id="tabs-2" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div>
        <div id="tabs-3" class="ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"></div>
    </div>
    

    The problem is happening because the SlickGrid content now exits as a child of an element with the class ui-widget-content. Actually, there are 2 ancestors of the grid header that have that class - in the above code see <div id="tabs"> and <div id="tabs-1"> both have that class applied when tabs are created.

    The jQueryUI CSS rules that are supposed to apply to get the correct search icon are:

    .ui-icon {
        width: 16px;
        height: 16px;
        background-image: url(images/ui-icons_222222_256x240.png);
    }
    
    .ui-icon-search {
        background-position: -160px -112px;
    }
    
    .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
        border: 1px solid #d3d3d3;
        background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;
        font-weight: normal;
        color: #555555;
    }
    

    The markup for the icon is:

    <span style="float:right" class="ui-icon ui-icon-search ui-state-default ui-corner-all" title="Toggle search panel" onclick="toggleFilterRow()"></span>
    

    so therefore the CSS rules .ui-icon, .ui-icon-search and the first match of the 3rd rule .ui-state-default are applied.

    However when the same markup exists as a descendent of a element with the class .ui-widget-content, the 2nd part of the 3rd rule above (.ui-widget-content .ui-state-default) also matches which is more specific. See http://www.stuffandnonsense.co.uk/archives/images/specificitywars-05v2.jpg for a Star Wars themed explaination of CSS specificity. Essentially the background property of the 3rd rule that includes background-position:50% 50% is more specific than the single selector .ui-icon-search rule therefore overriding the correct background-position:-160px -112px.

    The solution

    Need to make the .ui-icon-search rule the same or more specific than the .ui-widget-content .ui-state-default rule which can be done by either:

    1. Adding !important to the rule
    2. Adding more selectors to the rule

    For example

    .ui-icon-search {
        background-position: -160px -112px !important;
    }
    

    or

    .ui-icon-search, .ui-widget-content .ui-icon-search {
        background-position: -160px -112px;
    }
    

    I cannot think of a way that doesn't involve changing the jQueryUI CSS (or duplicating the .ui-icon-search rule in your own CSS with one of the two solutions above). I would actually be interested to see if there is another way myself!