【问题标题】:How to fix the position of an absolute overflowing element with respect to a relative parent?如何固定绝对溢出元素相对于相对父元素的位置?
【发布时间】:2015-12-21 04:19:33
【问题描述】:

我制作了一个自定义选择框,它被包裹在一个可滚动的 div 中。

我的问题是:下拉列表占用了包装器的空间。也就是说,它看起来像这样:

但是,我希望它像这样针对父包装器进行修复:

我可以通过从.select_box 中删除position:relative; 来实现此结果。但是,它打破了输入框和列表之间的间距(我不想要),如下所示:

这是我的代码--

HTML:

<div id="wrapper">
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
    <br/><br/>
    <div class="select_box">
        <input type="text" onMouseDown="show_list(this)" onblur="hide_list(this)" readonly/>
        <ul style="width:200px;">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
            <li>11</li>
            <li>12</li>
            <li>13</li>
        </ul>
    </div><br/><br/>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
</div>

jQuery:

function show_list(element) {
    $(element).next().toggle();
    if ($(element).next().css('display') == 'none') $(element).css('background', 'url(select_box_arrow.png) no-repeat 95%');
    else $(element).css('background', 'url(select_box_arrow_inverted.png) no-repeat 95%');
}

function hide_list(element) {
    $(element).next().hide();
    $(element).css('background', 'url(select_box_arrow.png) no-repeat 95%');
}
$(document).ready(function () {
    $("div[class='select_box'] input:text").css("padding", "0 10px");
    $("div[class='select_box'] li").mousedown(function () {
        $(this).parent().prev().attr('value', $(this).text());
    });
});

CSS:

#wrapper {
    height:200px;
    width:400px;
    border:Solid 1px;
    overflow:auto;
}
/* CSS for customized select box */
 .select_box {
    display:inline-block;
    //position:relative;
}
.select_box input[type="text"] {
    width:200px;
    height:25px;
    border: 1px solid #cccccc;
    border-radius:2px;
    background:url(select_box_arrow.png) no-repeat 95%;
    font-size:15px;
    outline:none;
    cursor:pointer;
    vertical-align:middle;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
.select_box input[type="text"]:focus {
    border-color:#FFC59D;
    box-shadow:0 0 10px #FFC59D;
}
.select_box ul {
    list-style:none;
    padding:0;
    margin:0;
    margin-top:2px;
    font-family:Tahoma, Geneva, sans-serif;
    line-height:25px;
    font-size:15px;
    font-weight:normal;
    border:solid 1px #FFC59D;
    width:220px;
    max-height:250px;
    overflow:auto;
    display:none;
    position:absolute;
    background:#fff;
    color:#000000;
    scrollbar-arrow-color: #ff6600;
    scrollbar-track-color: #FFC59D;
    scrollbar-face-color: #ff6600;
    scrollbar-shadow-color: #ff6600;
}
.select_box li {
    padding-left:10px;
}
.select_box li:hover {
    background:#FF9D5B;
    color:#fff;
    cursor:default;
}
.select_box ::-webkit-scrollbar {
    width: 12px;
    border:solid 1px #FFC59D;
    border-left-width:2px;
}
.select_box ::-webkit-scrollbar-thumb {
    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
    background:#FFC59D;
}
.select_box ::-webkit-scrollbar-thumb:window-inactive {
    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
    background:#FFC59D;
}

Working fiddle.

有没有简单的 CSS 解决方案?我也对通过 jQuery 的解决方案持开放态度。

【问题讨论】:

  • 将列表放入正文并使用点击事件定位。附加到正文是避免此类溢出问题的最常见方法
  • @charlietfl 可以试试。但是,这似乎是一个奇怪的解决方法。有没有办法通过简单的css解决这个问题?
  • 不,如果它是具有隐藏溢出的元素的后代,则无法告诉浏览器让它其中一些流到外面,而不是其余部分
  • @charlietfl 你不认为我需要用scroll 事件而不是click 重新定位列表吗?
  • 可能,我认为它就像一个下拉菜单,直到用户点击使用它才会显示

标签: javascript jquery html css css-position


【解决方案1】:

实现这一目标的最简单方法是尽可能使用原生 select 框。但是,如果您必须为输入框使用自定义列表,您可以尝试类似下面的示例。

Fiddle(你会看到我在文本输入框旁边添加了原生选择框,以显示默认情况下它是如何工作的)

HTML

<ul class="list-box" style="width:200px;">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
            <li>11</li>
            <li>12</li>
            <li>13</li>
        </ul>
<div id="wrapper">
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
    <br/><br/>
    <select><option>test</option><option>test</option><option>test</option><option>test</option><option>test</option><option>test</option><option>test</option><option>test</option><option>test</option><option>test</option><option>test</option></select>
    <div class="select_box">
        <input class="list_input" type="text" onMouseDown="show_list(this)" onblur="hide_list(this)" readonly/>
    </div><br/><br/>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
</div>

Javascript

function show_list(element) {
    var pos = $(element).offset();
    var input_height = $(element).height();
    $('.list-box').css('top', pos.top + input_height);
    $('.list-box').css('left', pos.left);
    $('.list-box').toggle();
    if ($('.list-box').css('display') == 'none') $(element).css('background', 'url(select_box_arrow.png) no-repeat 95%');
    else $(element).css('background', 'url(select_box_arrow_inverted.png) no-repeat 95%');
}

function hide_list(element) {
    $(element).next().hide();
    $(element).css('background', 'url(select_box_arrow.png) no-repeat 95%');
}
$(document).ready(function () {
    $("div[class='select_box'] input:text").css("padding", "0 10px");
    $("ul.list-box li").mousedown(function () {
        $('.list_input').attr('value', $(this).text());
        $('.list-box').toggle();
    });

    $('#wrapper').on('scroll', function(){
        var pos = $('.list_input').offset();
        var input_height = $('.list_input').height();
        $('.list-box').css('top', pos.top + input_height);
        $('.list-box').css('left', pos.left);
    });
});

CSS

#wrapper {
    height:200px;
    width:400px;
    border:Solid 1px;
    overflow:auto;
}
/* CSS for customized select box */
 .select_box {
    display:inline-block;
    position:relative;
}
.select_box input[type="text"] {
    width:200px;
    height:25px;
    border: 1px solid #cccccc;
    border-radius:2px;
    background:url(select_box_arrow.png) no-repeat 95%;
    font-size:15px;
    outline:none;
    cursor:pointer;
    vertical-align:middle;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
.select_box input[type="text"]:focus {
    border-color:#FFC59D;
    box-shadow:0 0 10px #FFC59D;
}
.select_box ul {
    list-style:none;
    padding:0;
    margin:0;
    margin-top:2px;
    font-family:Tahoma, Geneva, sans-serif;
    line-height:25px;
    font-size:15px;
    font-weight:normal;
    border:solid 1px #FFC59D;
    width:220px;
    max-height:250px;
    overflow:auto;
    display:none;
    position:absolute;
    background:#fff;
    color:#000000;
    scrollbar-arrow-color: #ff6600;
    scrollbar-track-color: #FFC59D;
    scrollbar-face-color: #ff6600;
    scrollbar-shadow-color: #ff6600;
}
.select_box li {
    padding-left:10px;
}
.select_box li:hover {
    background:#FF9D5B;
    color:#fff;
    cursor:default;
}
.select_box ::-webkit-scrollbar {
    width: 12px;
    border:solid 1px #FFC59D;
    border-left-width:2px;
}
.select_box ::-webkit-scrollbar-thumb {
    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
    background:#FFC59D;
}
.select_box ::-webkit-scrollbar-thumb:window-inactive {
    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
    background:#FFC59D;
}

所做更改的简要说明:

正如@charlietfl 提到的,列表需要附加到正文而不是滚动元素内。从那里,我将类添加到输入类型文本和列表中,因为父 jquery 选择器将不再工作,因为它们彼此不相邻或不在同一个父容器中。单击输入或滚动#wrapper div 时,我将列表放在单击的文本框的正下方。

【讨论】:

  • 感谢您的帮助! :)
【解决方案2】:

像这样?

你需要将下拉菜单移到#wrapper之外,然后用javaScript和position: absolute计算它相对于input[type=text]的位置

工作演示: http://jsfiddle.net/4rv4s3ce/10/

希望这会有所帮助。

【讨论】:

  • 感谢您的帮助! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 2016-04-07
相关资源
最近更新 更多