2

I'm building a custom dropdown element for a form and am now altering code I found here: https://codepen.io/qwertie/pen/QBYMdZ

I want the li items to take the space they need horizontally. If I set the width of .cb-item to 200px manually it sort of works, but I want it to scale automatically.

I tried setting display: inline-block and display: flex on .cb-item. I played around with all values in justify-content, but I can't get the items in the dropdown to use the width of the contents of each li item.

How can I do so?

CSS

/* ------------------------------------------ */
/* ----- combobox / dropdown list styling     */
/* ------------------------------------------ */

.less-sticky {
    border-radius: 10px;
    background-color: red !important;

    max-height: 200px;
    margin-top: 7px;
    background-color: rgb(255, 255, 255);
    border-bottom-left-radius: 3px;
    border-bottom-right-radius: 3px;
    z-index: 10;
    overflow-y: scroll !important;
    overflow-x: hidden !important;
    border-width: 0px 1px 1px;
    border-style: solid solid solid;
    border-color: rgb(220, 220, 220) rgb(220, 220, 220) rgb(220, 220, 220);
}

.dropdown {
    /* "relative" and "inline-block" (or just "block") are needed
     here so that "absolute" works correctly in children */
    position: relative;
    display: inline-block;
}

    .dropdown > *:last-child {
        /* Using `display:block` here has two desirable effects:
     (1) Accessibility: it lets input widgets in the dropdown to
         be selected with the tab key when the dropdown is closed. 
     (2) It lets the opacity transition work.
     But it also makes the contents visible, which is undesirable 
     before the list drops down. To compensate, use `opacity: 0`
     and disable mouse pointer events. Another side effect is that
     the user can select and copy the contents of the hidden list,
     but don't worry, the selected content is invisible. */
        display: block;
        opacity: 0;
        pointer-events: none;
        transition: 0.4s; /* fade out */
        position: absolute;
        left: 0;
        top: 100%;
        border: 1px solid #888;
        background-color: #fff;
        box-shadow: 1px 2px 4px 1px #666;
        box-shadow: 1px 2px 4px 1px #4448;
        z-index: 9999;
        min-width: 100%;
        box-sizing: border-box;
    }
    /* List of situations in which to show the dropdown list.
   - Focus dropdown or non-last child of it => show last-child
   - Focus .downarrow of combobox => show last-child
   - Stay open for focus in last child, unless .less-sticky
   - .sticky last child stays open on hover
   - .less-sticky stays open on hover, ignores focus in last-child */
    .dropdown:focus > *:last-child,
    .dropdown > *:focus ~ *:last-child,
    .dropdown > .less-sticky:last-child:hover {
        display: block;
        opacity: 1;
        transition: 0.15s;
        pointer-events: auto;
    }
/* detect Edge/IE and behave if though less-sticky is on for all
   dropdowns (otherwise links won't be clickable) */
@supports (-ms-ime-align:auto) {
    .dropdown > *:last-child:hover {
        display: block;
        opacity: 1;
        pointer-events: auto;
    }
}
/* detect IE and do the same thing. */
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
    .dropdown > *:last-child:hover {
        display: block;
        opacity: 1;
        pointer-events: auto;
    }
}

.dropdown:not(.sticky) > *:not(:last-child):focus,
.dropdown:focus {
    pointer-events: none; /* Causes second click to close */
}

.downarrow:focus {
    outline: 2px solid #8BF; /* Edge/IE can't do outline transparency */
    outline: 2px solid #48F8;
}


/* ------------------------------------------ */
/* ----- Styling for examples                 */
/* ------------------------------------------ */

.cb-item {
    display: block;
    margin: 0px;
    padding: 2px;
    color: #000;
}

    .cb-item:hover, .cb-item:hover > a:visited {
        color: #fff;
        background-color: #88f;
    }

HTML

<div class="dropdown">
    <span tabindex="0">dropdown menu V</span>
    <div class="less-sticky">
        <ul>
          <li class="cb-item"><a href="http://yes.net">home page</a></li>
          <li class="cb-item"><a href="http://test.net">My home page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">fd gddsfgpage</a></li>
          <li class="cb-item"><a href="#">457567456756 757this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
        </ul>
    </div>
</div>
2

3 Answers 3

2

try add this

ul{
width: max-content;
margin:0;
padding:0;
}

the max-content give the width of the max width of childs

/* ------------------------------------------ */
/* ----- combobox / dropdown list styling     */
/* ------------------------------------------ */

.less-sticky {
    border-radius: 10px;
    background-color: red !important;

    max-height: 200px;
    margin-top: 7px;
    background-color: rgb(255, 255, 255);
    border-bottom-left-radius: 3px;
    border-bottom-right-radius: 3px;
    z-index: 10;
    overflow-y: scroll !important;
    overflow-x: hidden !important;
    border-width: 0px 1px 1px;
    border-style: solid solid solid;
    border-color: rgb(220, 220, 220) rgb(220, 220, 220) rgb(220, 220, 220);
}

.dropdown {
    /* "relative" and "inline-block" (or just "block") are needed
     here so that "absolute" works correctly in children */
    position: relative;
    display: inline-block;
}

    .dropdown > *:last-child {
        /* Using `display:block` here has two desirable effects:
     (1) Accessibility: it lets input widgets in the dropdown to
         be selected with the tab key when the dropdown is closed. 
     (2) It lets the opacity transition work.
     But it also makes the contents visible, which is undesirable 
     before the list drops down. To compensate, use `opacity: 0`
     and disable mouse pointer events. Another side effect is that
     the user can select and copy the contents of the hidden list,
     but don't worry, the selected content is invisible. */
        display: block;
        opacity: 0;
        pointer-events: none;
        transition: 0.4s; /* fade out */
        position: absolute;
        left: 0;
        top: 100%;
        border: 1px solid #888;
        background-color: #fff;
        box-shadow: 1px 2px 4px 1px #666;
        box-shadow: 1px 2px 4px 1px #4448;
        z-index: 9999;
        min-width: 100%;
        box-sizing: border-box;
    }
    /* List of situations in which to show the dropdown list.
   - Focus dropdown or non-last child of it => show last-child
   - Focus .downarrow of combobox => show last-child
   - Stay open for focus in last child, unless .less-sticky
   - .sticky last child stays open on hover
   - .less-sticky stays open on hover, ignores focus in last-child */
    .dropdown:focus > *:last-child,
    .dropdown > *:focus ~ *:last-child,
    .dropdown > .less-sticky:last-child:hover {
        display: block;
        opacity: 1;
        transition: 0.15s;
        pointer-events: auto;
    }
/* detect Edge/IE and behave if though less-sticky is on for all
   dropdowns (otherwise links won't be clickable) */
@supports (-ms-ime-align:auto) {
    .dropdown > *:last-child:hover {
        display: block;
        opacity: 1;
        pointer-events: auto;
    }
}
/* detect IE and do the same thing. */
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
    .dropdown > *:last-child:hover {
        display: block;
        opacity: 1;
        pointer-events: auto;
    }
}

.dropdown:not(.sticky) > *:not(:last-child):focus,
.dropdown:focus {
    pointer-events: none; /* Causes second click to close */
}

.downarrow:focus {
    outline: 2px solid #8BF; /* Edge/IE can't do outline transparency */
    outline: 2px solid #48F8;
}


/* ------------------------------------------ */
/* ----- Styling for examples                 */
/* ------------------------------------------ */

.cb-item {
    display: block;
    margin: 0px;
    padding: 2px;
    color: #000;
}

    .cb-item:hover, .cb-item:hover > a:visited {
        color: #fff;
        background-color: #88f;
    }


ul{
width: max-content;
margin:0;
padding:0;
}
<div class="dropdown">
    <span tabindex="0">dropdown menu V</span>
    <div class="less-sticky">
        <ul>
          <li class="cb-item"><a href="http://yes.net">home page</a></li>
          <li class="cb-item"><a href="http://test.net">My home page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
          <li class="cb-item"><a href="#">fd gddsfgpage</a></li>
          <li class="cb-item"><a href="#">457567456756 757this page</a></li>
          <li class="cb-item"><a href="#">Stay on this page</a></li>
        </ul>
    </div>
</div>

Sign up to request clarification or add additional context in comments.

Comments

0

in your case first of all you have to set the following order: remove the left padding space:

.less-sticky ul {
    padding-left:0;
}

then

.cb-item {
    min-width: 200px;
 }

add the minimum width to the width of the specified item then you have to adjust the drop down wrapper: from

.dropdown > *:last-child {
 min-width: 100%;
}

to

.dropdown > *:last-child {
 width: auto;
}

in standard way the width is auto but you have to set it in order of cross browser support. the main containers always should contain the general codes so remove the min-width from the main container then add it to the item you want the effect occur so add it to the cb-item. there are some minor differences between the width and min or max width so they may cause some mistakes. i tried your code inside the codepen so it worked fine, please ask any questions if needed. hope this make sense.

1 Comment

correct and adjust the user agents as well, they will cause some minor problems,change the ul left side padding to "0" it contains a value of '40px' already which will push the items throw.
0

Try this: https://jsfiddle.net/samjco/paxfv1jt/74/

CSS:

        .dd-box{
        border: 1px solid;
        padding: 10px 0 10px 8px;
        margin: 0 !important;
        border-radius: 3px;
        width: 182px !important;
        display: block;
        z-index: 10;
        cursor: pointer;

        }
        .plus{    
        float: right;
        margin-right: 14px;
        vertical-align: middle;
        }

        .less-sticky {
        border-radius: 0px 0px 3px 3px;
        margin-top: -2px;
        z-index: 0;
        }

        .dropdown {
            position: relative;
            display: inline-block;
        }

        .dropdown > *:last-child {
        display: block;
        opacity: 0;
        pointer-events: none;
        transition: 0.4s;
        position: absolute;
        left: 0;
        top: 100%;
        border: 1px solid #888;
        border-top: 0px;
        background-color: #fff;
        box-shadow: 2px 10px 10px -5px #4444444a;
        min-width: 100%;
        box-sizing: border-box;
        }

            .dropdown:focus > *:last-child,
            .dropdown > *:focus ~ *:last-child,
            .dropdown > .less-sticky:last-child:hover {
                display: block;
                opacity: 1;
                transition: 0.15s;
                pointer-events: auto;
            }

        @supports (-ms-ime-align:auto) {
            .dropdown > *:last-child:hover {
                display: block;
                opacity: 1;
                pointer-events: auto;
            }
        }
        /* detect IE and do the same thing. */
        @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
            .dropdown > *:last-child:hover {
                display: block;
                opacity: 1;
                pointer-events: auto;
            }
        }

        .dropdown:not(.sticky) > *:not(:last-child):focus,
        .dropdown:focus {
            pointer-events: none; /* Causes second click to close */
        }

        .downarrow:focus {
            outline: 2px solid #8BF; 
            outline: 2px solid #48F8;
        }



        .cb-item {
        display: block;
        margin: 0px;
        color: #000;
        width: 190px;
        text-align: center;
        }
        a.cb-item {
        color: #000;
        }

            .cb-item:hover, .cb-item:hover > a:visited {
                color: #fff;
                background-color: #eee;
            }

            .cb-item-a{
              padding: 10px 20px;
        border-top: 1px solid;
        display: block;
            color: #000;
            text-decoration: none;
            }


        ul{
        width: max-content;
        margin:0;
        padding:0;
        }

HTML:

<div class="dropdown">
<div class="dd-box" tabindex="0">Select Status <span class="plus"> + </span></div>
    <div class="less-sticky">
        <ul>
          <li class="cb-item"><a class="cb-item-a" href="#">Open</a></li>
          <li class="cb-item"><a class="cb-item-a" href="#">Revised</a></li>
          <li class="cb-item"><a class="cb-item-a" href="#">In Review</a></li>
          <li class="cb-item"><a class="cb-item-a" href="#">Complete</a></li>
          <li class="cb-item"><a class="cb-item-a" href="#">Ready</a></li>
          <li class="cb-item"><a class="cb-item-a" href="#">Assigned</a></li>
          <li class="cb-item"><a class="cb-item-a" href="#">Working</a></li>

        </ul>
    </div>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.