Remplacer jQuery par du CSS

Ce sujet est résolu
37685
,

Bonjour,

J'ai un peu hésité à poster dans le forum CSS plutôt qu'ici...

Voilà mon soucis,
j'utilise jQuery pour cacher et afficher des divs, au survol d'autres div.
Ça fonctionne bien je suis content,
mais j'utiilise jQuery, et par soucis de performance, j'aurai aimé réussir à faire la même chose avec seulement du CSS (à la place de jQuery).

Je pensais y arriver avec des keyframes et animation, mais en fait je me demande si c'est vraiment possible... Je bloque complètement.

Ce qui est bloquant c'est que je dois afficher/cacher une div, quand je survol une AUTRE div.
À force de galérer je me demande si c'est vraiment possible...

J'ai fais une petite page de test pour avoir un visuel :

<!DOCTYPE html>
<head>
</head>
<body>
    <div class="top-bar">
        <div>
            <span id="top-bar-menu-icon">MENU</span>
            <span id="top-bar-user-icon">LOGIN</span>
        </div>
    </div>

    <!-- les 2 "nav" qu'on veut afficher au survol -->

    <!-- LOGIN -->
    <nav id="menu-user">
        <ul>
            <li><a href="#">Connexion</a></li>
            <li><a href="#">Inscription</a></li>
        </ul>
    </nav>

    <!-- MENU -->
    <nav id="menu">
        <ul>
            <li><a href="#">Lien 1</a></li>
            <li><a href="#">Lien 2</a></li>
            <li><a href="#">Lien 3</a></li>
        </ul>
    </nav>


    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script>
        slide_duration = 400;

        /* *******************************
                    LOGIN
        ******************************* */
        function show_user_menu()
        {
            $( '#menu' ).stop().slideUp(slide_duration);
            $( '#menu-user' ).stop().slideDown(slide_duration);
        }

        function hide_user_menu()
        {
            setTimeout(function()
            {
                if ($( '#menu-user:hover' ).length == 0 && $( '#top-bar-user-icon:hover' ).length == 0)    
                {
                    $( '#menu-user' ).stop().slideUp(slide_duration);
                }
            }, 100);
        }

        $( '#top-bar-user-icon' ).hover(function ()       { show_user_menu(); });
        $( '#top-bar-user-icon' ).mouseleave(function ()  { hide_user_menu(); });
        $( '#menu-user' ).mouseleave(function ()          { hide_user_menu(); });



        /* *******************************
                    MENU
        ******************************* */
        function show_menu()
        {
            $( '#menu-user' ).stop().slideUp(slide_duration);
            $( '#menu' ).stop().slideDown(slide_duration);
        }

        function hide_menu()
        {
            setTimeout(function()
            {
                if ($( '#menu:hover' ).length == 0 && $( '#top-bar-menu-icon:hover' ).length == 0)    
                {
                    $( '#menu' ).stop().slideUp(slide_duration);
                }
            }, 100);
        }

        $( '#top-bar-menu-icon' ).hover(function ()         { show_menu(); });
        $( '#top-bar-menu-icon' ).mouseleave(function ()    { hide_menu(); });
        $( '#menu' ).mouseleave(function ()                 { hide_menu(); });
    </script>
</body>
</html>

Même si vous me dites qu'on ne peut pas le faire,
alors c'est bien aussi, au moins j'arrêterai de me prendre la tête pour rien xD

Merci.

5 Réponse

48587
,

Tu ne peux agir que sur les éléments que fournit CSS.

En règle générale, on met le bloque qui dois s'afficher dans l'élément où la souris doit se trouver.

Donc ton cas, ça doit ressemble à ça :

<span id="top-bar-user-icon">
         LOGIN
         <nav id="menu-user">
        <ul>
            <li><a href="#">Connexion</a></li>
            <li><a href="#">Inscription</a></li>
        </ul>
    </nav>
</span>

le "top-bar-user-icon" doit être en position:relative;
et le "menu-user" en position:absolute; display:none;

De cette manière, quand tu mettras ta souris sur "login", tu peux dire #top-bar-user-icon:hover #menu-user { display:block; }
Sachant que lorsque ta souris ira sur le lien "connexion", tu seras toujours "hover" #top-bar-user-icon, donc le bloc restera actif.

37685
,

Finalement mes trucs sont annulés ^^

en fait j'ai eu du mal parce-que j'étais partis dans l'idée d'utiliser des keyframes mais c'était nul...
J'ai fais autre chose de plus simple.

En reprenant mon petit exemple d'en haut,
voilà ce que j'ai fais : (j'ai aussi viré les 'id' pour des 'class')

<!DOCTYPE html>
<head>
    <style type="text/css">
        .top-bar-user-icon,
        .menu-user {
            background-color: yellow;
        }
        .top-bar-menu-icon,
        .menu {
            background-color: orange;
        }

        .menu-user,
        .menu {
            min-width: 100px;
        }

        /* ********** Code utile *********** */

        .container-top-bar > ul li {
            display: inline;
        }

        .top-bar-user-icon,
        .top-bar-menu-icon {
            position: relative;
        }
        .menu-user,
        .menu {
            position: absolute;
            max-height: 0;
            overflow: hidden;
            transition: max-height 0.6s;
        }

        .top-bar-user-icon:hover .menu-user,
        .top-bar-menu-icon:hover .menu {
            max-height: 100px;
        }
    </style>
</head>
<body>

    <nav class="container-top-bar">
        <ul>
            <li class="top-bar-menu-icon">
                MENU
                <ul class="menu">
                    <li><a href="#">Lien 1</a></li>
                    <li><a href="#">Lien 2</a></li>
                    <li><a href="#">Lien 3</a></li>
                </ul>
            </li>

            <li class="top-bar-user-icon">
                LOGIN
                <ul class="menu-user">
                    <li><a href="#">Connexion</a></li>
                    <li><a href="#">Inscription</a></li>
                </ul>
            </li>
        </ul>
    </nav>

</body>
</html>

Si un menu est plus long que l'autre,
il faut juste dissocier les 2 dans le css, pour leur mettre un max-height différent, ou alors un temps de transition différent.

En tous cas,
ça fait moins de code, et c'est plus performant, c'est parfait.

Encore merci Kenor.

37685
, Il a répondu à ma question !

Oh super,
Je pense que j'y arriverai.

Mais là je suis crevé je vais aller dormir, et demain je ne pourrai pas bosser,
mais samedi je fais ça.

Ça me semble clair,
je me mets le sujet en résolu,
et je viendrai quand même faire un retour dans 2 jours.

Merci Kenor !

48587
, Il a répondu à ma question !

Vu que tu aimes visiblement faire bien les choses, je te conseil de te renseigner sur la méthode BEM par rapport aux noms de tes classes.
C'est vraiment quelque chose qui a changé ma façon de faire, et c'est nettement plus propre, d'autant plus lorsque le projet est gros.

    <nav class="top_bar">
        <ul class="top_bar-in">
            <li class="top_bar-item tob_bar-item--menu">
                MENU
                <ul class="menu">
                    <li class="menu-item"><a href="#" class="menu-link">Lien 1</a></li>
                    <li class="menu-item"><a href="#" class="menu-link">Lien 2</a></li>
                    <li class="menu-item"><a href="#" class="menu-link">Lien 3</a></li>
                </ul>
            </li>

            <li class="top_bar-item tob_bar-item--user">
                LOGIN
                <ul class="menu menu--user">
                    <li class="menu-item"><a href="#" class="menu-link">Connexion</a></li>
                    <li class="menu-item"><a href="#" class="menu-link">Inscription</a></li>
                </ul>
            </li>
        </ul>
    </nav>

Voilà en gros ce que ça donnerai :)
En gros, le nom principale ne doit pas contenir de tiret simple, d'où le "_" plutôt que "-" (top_bar)
L'enfant doit être séparé avec un tiret, pour dire qu'il est l'enfant de top_bar, donc top_bar-in ou top_bar-item (on aurai pu faire top_bar-in-item)
Et un "modifier" (en anglais) se sépare par 2 tirets, top_bar-item--user (on sait qu'il est sensé modifié le comportement de top_bar-item)
Et comme une classe est sensé être indépendante de sa balise, chaque élément est sensé avoir une classe propre (ce qui fait que tu peux utiliser ul/li, mais ailleurs, div/span et que ça fonctionne de la même manière).

37685
, Il a répondu à ma question !

Ah effectivement ça m'interresse beaucoup.

Je galère toujours avec mes noms de classe, je m'y perd, je m'embrouille...
Quelques fois c'est source de bug, je perd du temps à chercher...

J'aime beaucoup,
j'adopte ^^

Merci.