mouseover () mouseout () jQuery добавляет/удаляет проблему с классом

Я пытаюсь создать простой эффект наведения мыши, используя комбинацию наведения мыши, наведения мыши, добавления класса и удаления класса. По сути, когда пользователь наводит курсор мыши на элемент, я хочу применить другую границу (1 пиксель, пунктирная серая). Исходное состояние — «1px сплошной белый». У меня есть класс под названием «выделение», в котором просто есть «граница: 1px пунктирная серая». Я хочу добавить этот класс в onmouseover и удалить его в onmouseout, но я не могу получить желаемый эффект, если не использую !important в классе «highlight».


person Brian David Berman    schedule 11.05.2009    source источник
comment
Кстати, Брайан: поскольку вы используете jQuery, вы можете проверить вспомогательный метод события наведения: docs .jquery.com/Events/hover   -  person Shog9    schedule 11.05.2009


Ответы (7)


Похоже, что у вас и так нормально работает javascript, но это всего лишь проблема со спецификой ваши правила CSS, поэтому !important заставляет его работать.

Вам просто нужно сделать выделенные правила css более конкретными, чем невыделенные правила.

#someItem ul li { /* Specificity = 102 */
    border-color: white;
}

.highlight { /* Specificity = 10 -- not specific enough! */
    border-color: grey;    
}

#someItem ul li.highlight { /* Specificity = 112 -- this will work */
    border-color: grey;    
}

Изменить с дальнейшими пояснениями.
Допустим, соответствующие части вашего HTML-кода выглядят так:

<div id="someItem">
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
    </ul>
</div>

и у вас есть этот CSS:

#someItem ul li {
    border: 1px solid white;
}
.highlight {
    border-color: grey;
}

В настоящее время все элементы списка в ul в #someItem div будут иметь белую рамку, и ничто не имеет класса highlight, поэтому ничего не будет серым.

С помощью любых средств, которые вы хотите (в вашем случае событие наведения в jQuery), вы добавляете класс к одному из элементов:

$(this).addClass('highlight'); 

Теперь HTML будет выглядеть примерно так:

<div id="someItem">
    <ul>
        <li>Item 1</li>
        <li class="highlight">Item 2</li>
        <li>Item 3</li>
    </ul>
</div>

Пока ваш Javascript и HTML работают нормально, но вы не видите серой рамки! Проблема в вашем CSS. Когда браузер пытается решить, как стилизовать элемент, он просматривает все различные селекторы, предназначенные для элемента, и стили, определенные в этих селекторах. Если есть два разных селектора, определяющих один и тот же стиль (в нашем случае цвет границы оспаривается), то он должен решить, какой стиль применить, а какой игнорировать. Он делает это с помощью так называемой «специфичности», то есть того, насколько специфичен селектор. Как указано в HTML Dog article, он делает это, присваивая значение каждой части вашего селектор, и тот, кто набрал наибольшее количество очков, побеждает. Точки:

  • селектор элемента (например: "ul", "li", "table") = 1 балл
  • селектор класса (например: ".highlight", ".active", ".menu") = 10 баллов
  • селектор идентификатора (например: "#someItem", "#mainContent") = 100 баллов

Есть еще несколько правил, например: ключевое слово !important, а также встроенные стили, но это в основном не имеет значения для этого, эээ... "урока". Единственное, что вы должны знать, это то, что если два селектора имеют одинаковую специфичность, то выигрывает тот, который определен позже в файле.

Возвращаясь к вашей проблеме, учитывая CSS, который у нас был раньше, мы можем понять, почему у него до сих пор нет серой рамки:

#someItem ul li = id + element + element = 100 + 1 + 1 = 102 points
.highlight = class = 10 points

Как упоминалось ранее, решение состоит в том, чтобы создать более конкретный селектор:

#someItem ul li.highlight
   = id + element + element + class
   = 100 + 1 + 1 + 10
   = 112 points

И чтобы ответить на ваш вопрос в комментариях, вам не нужно менять какой-либо ваш javascript или HTML, чтобы это работало. Если вы сломаете этот селектор, он говорит следующее:

Найдите элемент с идентификатором «someItem», внутри которого найдите элемент ul, а затем элемент li с классом «highlight».

... и теперь, учитывая простой вызов .addClass(), который вы сделали ранее, li удовлетворяет этим условиям, поэтому граница должна стать серой.

person nickf    schedule 11.05.2009
comment
@nickf: Я думаю, ты что-то здесь понял. Как я мог тогда использовать метод addClass? Я изменил свою специфику, но теперь, как мне ссылаться на класс в jQuery в моем контексте? - person Brian David Berman; 11.05.2009
comment
Я думаю, что ваш jQuery в порядке, просто использование .addClass('highlight') и .removeClass('highlight') должно быть всем, что вам нужно сделать, если ваш CSS построен правильно. - person nickf; 11.05.2009
comment
Согласованный. Наиболее конкретное правило CSS будет иметь приоритет. Если вы установили базу с помощью #ItemList ul li, то установите стиль наведения с помощью #ItemList ul li.highlight, чтобы гарантировать более высокую специфичность. - person Cheekysoft; 11.05.2009
comment
@Cheekysoft: Как указать #ItemList ul li.highlight при использовании метода addClass/removeClass в jQuery? - person Brian David Berman; 12.05.2009
comment
как я уже сказал, вам вообще не нужно менять свой Javascript. Я отредактирую ответ, чтобы объяснить дальше. - person nickf; 13.05.2009

Начиная с Jquery 1.3.3, вы сможете сделать это немного проще. Будет выпущена расширенная версия .toggleClass(). доступный, который будет очень мощным.

Если вам не нужно разбивать это на функцию, то из 1.3.3 вы сможете просто сделать:

$(".myclass").hover(function(){ $(this).toggleClass('highlight'); });

Если вам необходимо включить !important, возможно, ваш класс выделения должен быть более конкретным (см. Специфика CSS< /а>).

person Community    schedule 11.05.2009

Я предполагаю, что вы используете встроенный стиль элемента для исходного стиля:

<style type="text/css">
  .hover { border: 1px dashed gray; } /* will never apply */
</style>

...

<!-- this style has priority over class styles! -->
<div style="border: 1px solid white"> 
...
</div>

Это переопределит стили, примененные с использованием класса... Поэтому вместо использования встроенных стилей просто используйте другой начальный класс для применения начальных стилей:

<style type="text/css">
  .normal { border: 1px solid white; }
  .hover { border: 1px dashed gray; }
</style>

...

<div class="normal">
...
</div>
person Shog9    schedule 11.05.2009
comment
Хорошая точка зрения. Просто чтобы уточнить для спрашивающего, использование метода css() в jquery применяет встроенные стили. - person TM.; 11.05.2009
comment
Я не использую встроенные стили. Исходный стиль применяется с помощью таблицы стилей, при этом ничего не применяется с помощью тега или метода css(), однако добавление другого класса с помощью addClass() НЕ переопределит правило стиля, уже определенное в исходном стиле, если только я не использую !important. - person Brian David Berman; 11.05.2009
comment
Затем убедитесь, что правило для исходного стиля либо менее конкретное, либо находится перед стилем выделения в таблице стилей. - person Shog9; 11.05.2009

Это пример наведения, которое я использовал:

$(".myclass").hover(jbhovershow,jbhoverhide);


jbhovershow = function () {
            $(this).addClass("jimtest");
          }; 

jbhoverhide = function () {
            $(this).removeClass("jimtest");
          }

вам действительно не нужно разбивать что-то такое простое на отдельные функции.

Я подозреваю, что ваша проблема может быть связана с конфликтом в css - попробуйте просто применить свой класс выделения, жестко запрограммировав его или щелкнув, и посмотрите, действительно ли он работает.

надеюсь, это поможет

Джим

person Jim    schedule 11.05.2009

Рассматривали ли вы чистый подход css?

Например:

someClass {
    border: 1px solid white;
}

someClass:hover {
    border: 1px dashed gray;
}

Псевдокласс hover даст вам желаемое поведение: когда пользователь наводит указатель мыши на элемент, он будет использовать нижний стиль, в противном случае он будет использовать первый стиль.

Примечание: как кто-то прокомментировал, это не работает для элементов, отличных от a, в IE. Однако у меня он работает в Chrome, Firefox, Safari и Opera.

Он также работает для любого элемента в стандартном режиме IE8 и IE7. У меня нет IE6 для тестирования.

person TM.    schedule 11.05.2009
comment
Я думаю, это не будет работать в IE6. В нем могут находиться только элементы. - person Paolo Bergantino; 11.05.2009
comment
@Paolo Кажется, работает во всех браузерах, кроме IE, для любого типа элементов. - person TM.; 11.05.2009
comment
@Паоло кажется, ты сказал две вещи. Сначала вы сказали, что это не будет работать в IE6. Затем вы сказали, что наведение работает только с элементами. Извините за непонимание, но я думал, вы говорите, что это работает только для элементов в любом браузере и вообще не работает в IE6. - person TM.; 11.05.2009
comment
когда я сказал, что в нем можно зависнуть, я имел в виду, что это как в IE6 - person Paolo Bergantino; 11.05.2009

CSS:

div.target {
    border: 1px solid #000000;
}

div.target-hover {
    border-color: #ff0000;
}

JS:

$("div.target").hover(
    function () {
        $(this).addClass("target-hover");
    },
    function () {
        $(this).removeClass("target-hover");
    }
);

я обычно делаю так. (позволяет больше вариантов)

person Chad Scira    schedule 11.05.2009
comment
Это именно то, что я делаю, за исключением того, что в div.target-hover у меня есть граница: 1px, пунктирная серая. Граница не переопределит оригинал, если по какой-то причине я не добавлю !important. - person Brian David Berman; 11.05.2009
comment
странно, как вы добавляете первый класс к элементу? - person Chad Scira; 11.05.2009
comment
@Chad Это происходит из правила под названием #ItemList ul li, которое я стилизовал так, чтобы оно имело рамку: 1px сплошной белый. У меня есть класс под названием Highlight, который просто имеет границу: 1px пунктирно-серый, который я хочу переключить. - person Brian David Berman; 11.05.2009
comment
вы ориентируетесь на это так: $(#ItemList ul li).hover - person Chad Scira; 11.05.2009

Или вы можете просто сделать это с помощью простого CSS, используя:

#namehere { border: 1px solid #fff; }
#namehere:hover { border: 1px dashed #aaa }
person thomasin    schedule 30.09.2010
comment
Не уверен, что это решение для разных браузеров (пока), но опять же, я никогда не говорил, что это должно быть так. - person Brian David Berman; 30.09.2010