Адаптивное относительное изменение размера элемента + адаптивное наложение текста - PullRequest
2 голосов
/ 05 августа 2020

Я столкнулся с двумя проблемами при разработке раскрывающегося меню на основе изображений:

  1. Как бы долго я ни пытался, я НЕ могу получить элемент flex ed в контейнере чтобы высота оставалась такой же, как у соседнего элемента. [Если вы посмотрите на мой jsFiddle , каждое выдвигающееся содержимое, которое открывается при наведении, должно быть той же высоты, что и значки.]

  2. Я не могу понять текст поверх каждого изображения - я считаю, что это потому, что размер меню изменяется в зависимости от ширины устройства - от чего я не могу отказаться. Все источники, которые я видел, основаны на position:absolute, который я не смог заставить работать. [В частности, поверх каждого изображения должен быть текст, обозначающий их.]

Комментарий для уточнения, если необходимо.

Вот jsFiddle Спасибо.

Ответы [ 2 ]

1 голос
/ 17 августа 2020

Для ясности и повторного использования кода CSS разделен на четыре основных раздела:

  • Глобальные переменные, значения по умолчанию для страниц и переопределения стандартных значений HTML / CSS значений
  • Механизм , Настройки макета Flexbox и размеры / действия элементов
  • Простые шаблоны, интервалы, шрифты, границы
  • Яркие темы, любые цвета, связанные с использованием настраиваемого атрибута [theme="gr-blue"]. Можно легко расширить с помощью других тем.

Макет Flexbox

Для выравнивания .slideout-content слева и справа вы можете просто использовать row-reverse направление и justify-content: flex-end для нечетное .menu-item и направление по умолчанию row для четное .menu-item

Наложение текста изображения

Использует стандартную конструкцию родительского / дочернего элемента position: relative и absolute. Дочерний элемент content заполнен оверлейным текстом , полученным из data-overlay настраиваемого атрибута.

Замечания

  • Код сильно прокомментировал и показывает несколько альтернативных вариантов использования макета Flexbox.
  • Удалено filter: brightness(1.2), поскольку IE11 не может справиться с этим, потребуется какая-то альтернатива.
  • Я немного изменил непрозрачность цвета .slideout-content на показать некоторые эффекты наведения.
  • Где применимо, я добавил размеры, зависящие от области просмотра.
  • Удалено все использование дочернего элемента margin и перенесен интервал в родительский padding, где это применимо. Это особенно важно при использовании относительных размеров ('%') в сочетании с box-sizing: border-box, поскольку margin увеличивает размер дочернего элемента сверх 100%.
  • Не используйте flex: 1, чтобы разрешить элементам Grow, используйте flex-grow: 1 вместо этого для использования с IE11.
  • Измените dir="ltr" в <body> на 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 для получения дополнительной информации о позиционировании.

SNIPPET

/***********/
/* 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>
1 голос
/ 14 августа 2020

Вам нужно, чтобы menu-top отображался как flex, чтобы его содержимое растягивалось. Для наложения на изображение правило position: absolute является правильным, но для него также потребуется объявить одно из правил позиционирования top right bottom left, а его родительский элемент должен иметь позицию relative. Я создал фрагмент на основе flexbox на основе того, что вы описали. Обратите внимание, что я не использовал никаких столбцов, вместо этого дочерние элементы оборачиваются на 50%, и я использую :nth-child(odd) для выбора нечетных дочерних элементов и order: 1 или order: 2 правила соответственно для отображения меню слева или справа. Также обратите внимание, что я использовал класс .page__wrap в div, чтобы обернуть всю страницу, верхний колонтитул, основной и нижний колонтитулы, чтобы согнуть их, чтобы нижний колонтитул всегда находился внизу, даже если прокрутки нет.

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...