【问题标题】:Responsive Relative Element Resizing + Responsive Text Overlay响应式相对元素调整大小 + 响应式文本叠加
【发布时间】:2020-11-25 04:30:52
【问题描述】:

我在设计基于图像的下拉菜单时遇到了 2 个问题:

  1. 无论我尝试多长时间,我都无法让容器内的 flexed 元素保持与相邻元素相同的高度。 [如果你看我的jsFiddle,悬停显示的每个滑出内容都应该与图标高度相同。]

  2. 我无法在每张图片上显示文字 - 我相信这是因为菜单会根据设备宽度自行调整大小 - 我不能放弃。我看到的所有资源都基于position:absolute,我无法开始工作。 [具体来说,每张图片上面都应该有文字,标注出来。]

如有需要,请发表评论以进行澄清。

这是jsFiddle 谢谢。

【问题讨论】:

  • 嗨,Exosylver,回复很少。还需要这方面的帮助吗?
  • @RenevanderLende 是的!!
  • 问题:您是否希望<header><footer> 始终可见,或者可以有超过四个图像吗?是否需要当前的滚动行为?
  • @RenevanderLende 我确实希望在第一次加载时看到<header>,以及菜单(4 张图片)。 <footer> 应该粘在底部,这样在移动设备上,整个屏幕都会被利用(尽管在这种情况下不会滚动,因为页脚已经比它需要的低了)。所以,有滚动,只是页脚的高度。

标签: javascript html css image layout


【解决方案1】:

为了清晰和代码回收,CSS 被分为四个主要部分:

  • 标准 HTML/CSS 值的全局变量、页面默认值和覆盖
  • 机制、Flexbox 布局设置和元素大小/操作
  • 引人注目的泛型、间距、字体、边框
  • 眼睛糖果主题,使用自定义属性[theme="gr-blue"] 的任何颜色相关。可以使用其他主题轻松扩展。

弹性盒布局

对于.slideout-content 的左右对齐,您可以简单地使用row-reverse 方向和justify-content: flex-end 用于奇数 .menu-item 和默认row 方向用于甚至 .menu-item

图片文字叠加

使用标准的position: relativeabsolute 父/子元素构造。子content 填充了从data-overlay 自定义属性获得的覆盖文本

备注

  • 代码被大量注释并显示了 Flexbox 布局的一些替代用途。
  • 已删除 filter: brightness(1.2),因为 IE11 无法处理此问题,需要一些替代方法。
  • 我略微更改了.slideout-content 的颜色不透明度以显示一些悬停效果。
  • 在适用的情况下,我添加了取决于视口的尺寸。
  • 删除了对子 margin 的所有使用,并将间距移至父 padding(如果适用)。当使用相对大小 ('%') 与 box-sizing: border-box 结合使用时,这一点尤其重要,因为 margin 会将孩子的大小增加超过 100%。
  • 不要使用flex: 1 来允许元素增长,而是使用flex-grow: 1 来与IE11 一起使用。
  • <body> 中的dir="ltr" 更改为dir="rtl" 以测试文档阅读顺序。

经测试可与 Chrome/Edge、Firefox 和 IE11 兼容,最小尺寸为 320x480 像素,无需滚动。

更新 1 我忘了提到我删除了原始的 footer {...height: 5vh...},它的内容不够高,因此会溢出,在页脚下方创建一个白条。

如果您不希望页脚(或任何父元素)溢出,其height 必须至少大于/等于其子元素(ren)的高度(计算line-height + padding + border + margin =>是否添加padding + border取决于box-sizing)。

更新 2 为了在父级使用中将覆盖 .slideout::after 定位在顶部和中心的 3/4 处:.slideout::after { top: 75%; left: 50%; transform: translate(-50%, -50%) },我相应地修改了 CSS。查看w3schools: CSS Layout - Horizontal & Vertical Align了解更多定位信息。

片段

/***********/
/* GLOBALS */
/***********/
html,body           { width: 100%; max-width: 100%; height: 100% }

html                { -webkit-box-sizing: border-box; box-sizing: border-box }
*, *:before, *:after{ -webkit-box-sizing: inherit; box-sizing: inherit }

/* remove/override default element default */
html                { -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100% }
body                { margin: 0 }
ul,li               { list-style-type: none; padding: 0; margin: 0 }
a                   { text-decoration: none; color: inherit }
p                   { margin: 0; padding: 1em 0 }

/* for debugging (put in <body>) */
[outlines="1"] *    { outline: 1px dashed }

/*************/
/* MECHANISM */
/*************/

/******************/
/* Flexbox Layout */
/******************/

/* FBL EITHER (specific) */
/*.wrapper, .touch-menu, .menu-item,
.menu-item *                { display: flex }/**/

/* FBL OR (generic, if you want to insert elements on-the-fly without classes) */
div, ul, li, a, img         { display: flex }/**/

/* .wrapper is an FBL column of three main rows, pushed apart */
.wrapper                    { flex-direction: column; justify-content: space-between }

/* .touch-menu fills available space and is a row that wraps its kids */
.touch-menu                 { flex-grow: 1; flex-flow: row wrap }

/* 
   Because .menu-item width is 50% there will always be only two in a row,
   simply reverse FBL for first in a row...
*/
.menu-item:nth-child(odd)   { flex-direction: row-reverse } /* reverse row logic */
.menu-item:nth-child(odd)>* { justify-content: flex-end   } /* ditto */

.slideout-content           { flex-grow: 1 }           /* grow to fill parent */
.slideout-content ul        { flex-direction: column } /* a column of several rows */

.touch-menu,.slideout-content *, /* center all content rows/columns */
.header>*,.footer>*         { justify-content: center; align-content: center; align-items: center }
.footer>*                   { justify-content: flex-end } /* right align footer rows */

/**********/
/* Action */
/**********/
.slideout-content       { display: none } /* hide, change to 'flex' to verify positioning */

.slideout:hover+.slideout-content,
.slideout-content:hover { display: flex } /* show on hover */

/**********/
/* Sizing */
/**********/
.wrapper                { width: 100%; height: 100% }
.touch-menu             { padding: 0 5% }
/* modify 5% to required need, forces size of entire .menu-item */

.menu-item              { width: 50% } /* of .touch-menu */
.slideout               { width: 50%; position: relative } /* of .menu-item  */
.slideout::after        { position: absolute; bottom: 0; left: 0; right: 0 }

/* UPDATE 2 */
.slideout::after        { top: 75%; left: 50%; transform: translate(-50%, -50%) }


/* redundant, but > 50% will animate .slideout on hover */
.slideout-content       { width: 50% } /* otherwise: remove */

/* fill parent */
.header>*, .footer>*,
.slideout img           { width: 100% }
.slideout-content *     { width: 100%; height: 100% } /* modify to your needs */

/**********************/
/* EYE-CANDY generics */
/**********************/
.header                 { border-bottom-style: inset }
.header .headline       { padding: 0.67em 0; font-size: 2.6vw; font-weight: bold }
.touch-menu .menu-item  { padding: 1vh }

.slideout               { cursor: pointer }
.slideout::after        { content: attr(data-overlay); font-size: .75vw; padding: .25vw }

.slideout-content       { font-size: 1.5vw; padding: .25vw; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2) }
.slideout-content ul *  { border-radius: 0.5vw } 
.slideout-content li    { padding: .125vw }
.slideout-content a     { border: thin inset }

.footer                 { padding: 2.65vmin .75vw; font-size: .75vw; border-top: outset }

/* ONLY required when 'FBL EITHER' used */
.header                 { text-align: center }
.footer                 { text-align: right  }

/*********************/
/* EYE-CANDY theming */
/*********************/
body { font-family: "Lato", sans-serif }

body[theme="gr-blue"] {
    color: GoldenRod; 
    /*
        Permalink - use to edit and share this gradient:
        https://colorzilla.com/gradient-editor/#c7d7dd+0,a7cfdf+16,5085a0+57,23538a+100
    */
    background-color: rgb(199,215,221); /* Old browsers */
    background-image:    -moz-linear-gradient(top, rgba(199,215,221,1) 0%, rgba(167,207,223,1) 16%, rgba(80,133,160,1) 57%, rgba(35,83,138,1) 100%); /* FF3.6-15 */
    background-image: -webkit-linear-gradient(top, rgba(199,215,221,1) 0%, rgba(167,207,223,1) 16%, rgba(80,133,160,1) 57%, rgba(35,83,138,1) 100%); /* Chrome10-25,Safari5.1-6 */
    background-image:   linear-gradient(to bottom, rgba(199,215,221,1) 0%, rgba(167,207,223,1) 16%, rgba(80,133,160,1) 57%, rgba(35,83,138,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */

    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c7d7dd', endColorstr='#23538a',GradientType=0 ); /* IE6-9 */
}

[theme="gr-blue"] .header { color: AliceBlue; background-color: #605e5e; border-bottom-color: #888888 }
[theme="gr-blue"] .footer { background-color:#605e5e; border-color: GoldenRod }

[theme="gr-blue"] .slideout::after           { color: AliceBlue; background-color: rgba(115,110,111,.6) }
[theme="gr-blue"] .slideout-content          { background-color: rgba(115,110,111,.6) } /* #736e6f */
[theme="gr-blue"] .slideout-content a        { border-color: #888585 }
[theme="gr-blue"] .slideout-content li:hover { background-color: rgba(115,110,111,.6) }
<body theme="gr-blue" dir="ltr" outlines="0">
<div class="wrapper">
    <div class="header">
        <div class="headline">Links of Links</div>
    </div>

    <div class="touch-menu">
        <div class="menu-item">
            <div class="slideout" data-overlay="overlay 1">
                <img src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
            </div>
            <div class="slideout-content">
                <ul>
                    <li><a href="#">scaleLink 1</a></li>
                    <li><a href="#">scaleLink 2</a></li>
                    <li><a href="#">scaleLink 3</a></li>
                </ul>
            </div>
        </div>
        <div class="menu-item">
            <div class="slideout" data-overlay="overlay 2">
                <img src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
            </div>
            <div class="slideout-content">
                <ul>
                    <li><a href="#">bookLink 1</a></li>
                    <li><a href="#">bookLink 2</a></li>
                    <li><a href="#">bookLink 3</a></li>
                    <li><a href="#">bookLink 4</a></li>
                    <li><a href="#">bookLink 5</a></li>
                    <li><a href="#">bookLink 6</a></li>
                </ul>
            </div>
        </div>
        <div class="menu-item">
            <div class="slideout" data-overlay="overlay 3">
                <img src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
            </div>
            <div class="slideout-content">
                <ul>
                    <li><a href="#">ugavelLink 1</a></li>
                    <li><a href="#">ugavelLink 2</a></li>
                    <li><a href="#">ugavelLink 3</a></li>
                    <li><a href="#">ugavelLink 4</a></li>
                </ul>
            </div>
        </div>
        <div class="menu-item">
            <div class="slideout" data-overlay="overlay 4">
                <img src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
            </div>
            <div class="slideout-content">
                <ul>
                    <li><a href="#">lgavelLink 1</a></li>
                    <li><a href="#">lgavelLink 2</a></li>
                    <li><a href="#">lgavelLink 3</a></li>
                </ul>
            </div>
        </div>
    </div>

    <div class="footer">
        <div>
            Powered by <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=emb_logo" target="_blank">Barack Obama</a>
        </div>
    </div>
</div>
</body>

【讨论】:

  • 几乎完美。只有一件事:页面底部有一个白条,我需要背景从页眉一直延伸到页脚。
  • 你又把&lt;footer&gt;的高度改成5vh了吗?因为5vh的内容不够高,会使其溢出,所以下面的白条(由于&lt;p&gt;的高度和边距)。计算:父母身高必须 >= child(ren) line-height + padding + margin。我实际上忘了提及为什么我删除了footer.height,对不起。
  • 我实际上认为问题在于渐变背景突然切断,这让我认为这是页脚高度的问题。
  • 我发布的版本(再次测试)不显示页脚下方的白条,仅在调整大小时完全可以接受(Firefox 轻微白色,屏幕底部的 Chrome/Edge 空白行,取决于浏览器渲染图形,我猜)。但是,关于5vh 的页脚高度的评论仍然是正确的,我注意到这是第一次运行您的版本。如果渐变给您带来任何麻烦,请尝试 itsbackground-attachmentbackground-size 的各种选项。
  • 还有一件事:当所有叠加文本的大小不同时,如何将叠加层居中到顶部的 3/4,居中?
【解决方案2】:

您需要将menu-top 显示为flex 以使其内容伸展。对于图像上的覆盖,position: absolute 规则是正确的,但它还需要声明定位规则之一 top right bottom left,并且其父级必须具有 relative 位置。 我根据您的描述创建了一个基于 flexbox 的 sn-p。请注意,我没有使用任何列,而是子级以 50% 换行,我使用 :nth-child(odd) 选择奇数子级,并相应地使用 order: 1order: 2 规则来向左或向右显示菜单。 另请注意,我在 div 上使用了 .page__wrap 类来包装整个页面、页眉、主页面和页脚,以使它们弯曲,因此即使没有滚动,页脚也始终位于底部。

body {
  margin: 0;
}

.page__wrap {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

header {
  background-color: lightgray;
  border-bottom: 5px solid gray;
}

h2 {
  text-align: center;
  margin: 0;
  padding: 2em 0;
}

main {
  flex: 1;
}

footer {
  background-color: gold;
  padding: 1em 0;
  justify-self: flex-end;
}

.slideouts__wrapper {
  display: flex;
  flex-wrap: wrap;
  max-width: 65rem;
  margin: 0 auto;
}

.slideout {
  display: flex;
  margin: 10px;
  width: calc(50% - 20px);
  justify-content: flex-start;
}

.slideout:nth-child(odd) {
  justify-content: flex-end;
}

.slideout__avatar {
  background-color: red;
  flex: 0 1 auto;
  object-fit: cover;
  position: relative;
}

.slideout__avatar--image {
  display: block;
  width: 100%
}

.slideout__avatar--overlay {
  position: absolute;
  bottom: 0;
  width: 100%;
  background-color: #00000095;
  color: white;
  transition: .2s;
  display: flex;
  justify-content: center;
  align-items: center;
}

.slideout:nth-child(odd) .slideout__avatar {
  order: 2;
  position: relative;
}

.slideout__menu {
  display: flex;
  flex: 0 0 50%;
}

.slideout__menu--items {
  display: none;
  flex-direction: column;
  justify-content: stretch;
  margin: 0;
  padding:0;
  flex: 1;
  list-style: none;
  background-color: #736E6F;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  padding: 1%;
}

.slideout__menu--item {
  flex: 1;
  display: flex;
  border: thin inset #888585;
    border-radius: 5%;
}

.slideout__menu--item:hover {
  filter: brightness(1.2);
}

.slideout__menu--item--anchor {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  text-decoration: none;
    color: goldenrod;
}

.slideout__avatar:hover + .slideout__menu .slideout__menu--items {
  display: flex;
}

.slideout__avatar:hover .slideout__avatar--overlay {
  opacity: 1;
}

.slideout__menu--items:hover {
  display:flex;
}
<div class="page__wrap">
  <header>
    <div class="header__container">
      <h2>links of links</h2>
    </div>
  </header>
  <main class="slideouts__container">
    <div class="slideouts__wrapper">
      <div class="slideout">
        <div class="slideout__avatar">
          <img class="slideout__avatar--image" src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
          <div class="slideout__avatar--overlay">
            <p>the overlay</p>
          </div>
        </div>
        <div class="slideout__menu">
          <ul class="slideout__menu--items">
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 1</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 2</a></li>
          </ul>
        </div>
      </div>
      <div class="slideout">
        <div class="slideout__avatar">
          <img class="slideout__avatar--image" src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
          <div class="slideout__avatar--overlay">
            <p>the overlay</p>
          </div>
        </div>
        <div class="slideout__menu">
          <ul class="slideout__menu--items">
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 1</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 2</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 3</a></li>
          </ul>
        </div>
      </div>
      <div class="slideout">
        <div class="slideout__avatar">
          <img class="slideout__avatar--image" src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
          <div class="slideout__avatar--overlay">
            <p>the overlay</p>
          </div>
        </div>
        <div class="slideout__menu">
          <ul class="slideout__menu--items">
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 1</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 2</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 3</a></li>
          </ul>
        </div>
      </div>
      <div class="slideout">
        <div class="slideout__avatar">
          <img class="slideout__avatar--image" src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
          <div class="slideout__avatar--overlay">
            <p>the overlay</p>
          </div>
        </div>
        <div class="slideout__menu">
          <ul class="slideout__menu--items">
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 1</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 2</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 3</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 4</a></li>
          </ul>
        </div>
      </div>
      
    </div>
  </main>
  <footer>
    <div class="footer__container">
      <p>footer text</p>
    </div>
  </footer>
</div>

【讨论】:

  • 这与我想要的非常接近,但只有两件事:叠加层应该始终可见。 4 个框(菜单)需要根据页面宽度调整大小,因此在手机上可以看到滑出。
  • 这相当容易,将.slideout__avatar 上的flex 规则修改为0 1 auto 并将width: 100% 规则修改为图像.slideout__avatar--image,您基本上是在告诉容器相应地缩小到视口,尽管我想强调您需要添加一些限制/断点以提高可读性/可访问性。对于覆盖,您只需删除opacity: 0 规则并根据自己的喜好更改widthheight。我用更改更新了 sn-p,以便您可以看到它的实际效果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-26
  • 2018-04-22
  • 2021-01-01
  • 2022-01-26
  • 2018-05-06
相关资源
最近更新 更多