Знать, может ли элемент потенциально соответствовать другому элементу при изменении размера окна
Я ищу способ узнать, может ли элемент (меню) вписаться в другой элемент при изменении размера окна. Я не знаю ширину рассматриваемого элемента (например, он не установлен 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