Знать, может ли элемент потенциально соответствовать другому элементу при изменении размера окна

Я ищу способ узнать, может ли элемент (меню) вписаться в другой элемент при изменении размера окна. Я не знаю ширину рассматриваемого элемента (например, он не установлен CSS).

Содержание меню является динамическим и неизвестным по данным (язык) и количеству (роль пользователя / права).

Решение, которое я могу придумать, прекрасно работает, если в моей первой загрузке происходит подгонка элемента, потому что я сохраняю начальную ширину, но не очень хорошо работает, если элемент не подходит (скажем, при уменьшенном размере окна), Итак, мой вопрос, как я могу справиться с этим увеличением?

Пример HTML/CSS:
Посмотрите на фрагмент в полноэкранном режиме ("развернуть фрагмент"). Он обрывается на уровне около 604 пикселей, а адаптивное меню запускается с разрешением 480 пикселей.

.header {
  font-family: Arial, sans-serif;
  overflow: hidden;
  background: blue;
}

.header__logo {
  float: left;
  width: 100px;
  height: 40px;
  background: #000;
  color: #fff;
  text-align: center;
  line-height: 40px;
}

.menu {
  float: left;
  list-style: none;
  padding: 0;
  margin: 0;
}

@media screen and (max-width: 480px) {
  .menu {
    display: none;
  }
}

.menu__item {
  padding: 0 10px;
  color: #fff;
  float: left;
  height: 40px;
  line-height: 40px;
}

.hamburger {
  display: none;
  float: right;
  font-size: 20px;
  text-align: center;
  width: 40px;
  height: 40px;
  line-height: 40px;
  color: #fff;
}

@media screen and (max-width: 480px) {
  .hamburger {
    display: block;
  }
}
<div class="header">
  <div class="header__logo">logo</div>
  <div class="hamburger">=</div>
  <ul class="menu">
    <li class="menu__item">item 1</li>
    <li class="menu__item">item 2</li>
    <li class="menu__item">item 3</li>
    <li class="menu__item">item 4</li>
    <li class="menu__item">item 5</li>
    <li class="menu__item">item 6</li>
    <li class="menu__item">item 7</li>
  </ul>
</div>

2 ответа

Вы можете использовать медиа-запросы и что-то вроде fontawesome (есть и другие варианты) для отображения / скрытия значков и текста в определенных точках останова. Вы можете изменить размер экрана, чтобы найти значения пикселей.

Если вы ищете пример JS для определения конкретной ширины, это тоже можно сделать, но если это можно решить с помощью CSS, почему бы и нет!

.header {
  font-family: Arial, sans-serif;
  overflow: hidden;
  background: blue;
}
.header__logo {
  float: left;
  width: 100px;
  height: 40px;
  background: #000;
  color: #fff;
  text-align: center;
  line-height: 40px;
}
.menu {
  float: left;
  list-style: none;
  padding: 0;
  margin: 0;
}
@media screen and (max-width: 480px) {
  .menu {
    display: none;
  }
}
.menu__item {
  padding: 0 10px;
  color: #fff;
  float: left;
  height: 40px;
  line-height: 40px;
}
.hamburger {
  display: none;
  float: right;
  font-size: 20px;
  text-align: center;
  width: 40px;
  height: 40px;
  line-height: 40px;
  color: #fff;
}
@media screen and (max-width: 480px) {
  .hamburger {
    display: block;
  }
}
.menu__item .fa {
  display: none;
}
li.menu__item a {
  color: white;
  display: block;
}
/*(min-width:465px) and (max-width:545px) */
/* or whatever widths you need */
@media all and (min-width: 0) and (max-width: 1000px) {
  .menu__item a span {
    color: salmon;
    display: inline-block;
    text-indent: -9999px;
    text-align: center;
  }
  .menu__item a .fa {
    display: block;
    text-indent: 0;
    color: #a00;
    text-align: center;
    line-height: 40px;
  }
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<div class="header">
  <div class="header__logo">logo</div>
  <div class="hamburger">=</div>
  <ul class="menu">
    <li class="menu__item"><a href="#"><i class="fa fa-bell" aria-hidden="true"></i><span>item 1</span></a>
    </li>
    <li class="menu__item"><a href="#"><i class="fa fa-bell" aria-hidden="true"></i><span>item 2</span></a>
    </li>
    <li class="menu__item"><a href="#"><i class="fa fa-bell" aria-hidden="true"></i><span>item 3</span></a>
    </li>
    <li class="menu__item"><a href="#"><i class="fa fa-bell" aria-hidden="true"></i><span>item 4</span></a>
    </li>
    <li class="menu__item"><a href="#"><i class="fa fa-bell" aria-hidden="true"></i><span>item 5</span></a>
    </li>
    <li class="menu__item"><a href="#"><i class="fa fa-bell" aria-hidden="true"></i><span>item 6</span></a>
    </li>
    <li class="menu__item"><a href="#"><i class="fa fa-bell" aria-hidden="true"></i><span>item 7</span></a>
    </li>
  </ul>
</div>

Поэтому я нашел решение, которое работает довольно хорошо. Это в значительной степени вдохновлено работой Смешно реагирующих кнопок социального обмена

var Menu = (function() {
  // setup classes used
  var headerClass = 'header__wrapper';
  var elClass = 'main-nav';
  var itemsClass = 'main-nav__item';
  var smallClass = itemsClass + '--small';

  // setup jQuery elements
  var $header = $('.' + headerClass).not('.clone');

  // setup the clone used to make operations/checks
  var clone = '.clone.' + headerClass;

  // currently, only a set height is supported
  var originalHeight = 60;

  var stealth = function(el) {
    var $el = (el instanceof jQuery) ? el : $(el);

    $el.css({
      height: 'auto',
      // position absolute is needed to be out of the DOM structure,
      // while still having a testable height
      position: 'absolute',
      left: 0,
      right: 0,
      visibility: 'hidden'
    });
  }

  return {
    init() {
      Menu.reset();
      Menu.exec();
      Menu.bindEvents();
    },

    exec() {
      // create a clone if it doesn't exist
      if (!$(clone).length) {
        Menu.clone(clone);
      }

      // reset the menu to its largest form
      Menu.reset();

      // does it fit?
      if (Menu.checkFit()) {
        // it fits, use the clone data;
        Menu.replace();
      } else {
        // it didn't fit, so attempt to fit
        Menu.attemptToFit();
      }
    },

    reset() {
      $(clone).find('.' + itemsClass).removeClass(smallClass);
    },

    bindEvents() {
      $(window).resize(function() {
        Menu.exec();
      });

      $(window).focus(function() {
        Menu.exec();
      });
    },

    checkFit() {
      return $(clone).height() == originalHeight;
    },

    attemptToFit() {
      var itemsArr = $(clone).find('.' + itemsClass).sort(function(a, b) {
        // TODO: handle and make sure nodes without data-priority are handled by DOM order
        var a = $(a).attr('data-priority') || 0;
        var b = $(b).attr('data-priority') || 0;

        return b - a;
      });

      // count iterations that do not fit
      var noFit = 0;

      // cycle over items, attempting to fit
      itemsArr.each(function(i) {
        var item = itemsArr[i];

        $(item).addClass(smallClass);

        // exit the loop if it fits!
        if (Menu.checkFit()) {
          // it fits, exit the loop!

          return false;
        } else {
          // this attempt didn't fit, try the next done
          noFit++;
        }
      });

      // could we make it fit?
      if (noFit == itemsArr.length - 1) {
        // TODO: handle this scenario
        // couldn't make it fit :( handle it
      } else {
        // we were able to make it fit, replace the original with the clone content
        Menu.replace();
      }
    },

    clone(el) {
      $header.clone().addClass('clone').insertAfter($header);
      stealth(el);
    },

    replace() {
      var content = $(clone).clone().contents();

      // replace the content of the original with the clone
      $header.empty().append(content);
    }
  };

})();

Menu.init();

Посмотрите это в действии на CodePen: http://codepen.io/veksen/pen/ORAmVa

Другие вопросы по тегам