Как отфильтровать все элементы страницы, выбрав только те, у которых есть определённое css свойство?
Всем привет, меня тут забодала одна фича.
Интро:
Все мы прекрасно понимаем, что для расположения блоков в одну линию достаточно использовать сетку. Все гриды, которые я использовал когда либо опираются на float (грёбаный костыль). Меня бы всё радовало, если бы флоуты действительно предназначались именно для расположения блоков в одну строку, но это не так и у свойства есть один побочный эффект.
Стандартно все блоки наследуют высоту по совокупности размещённых внутри дочерних блоков или строк. Но если мы дадим блоку float (неважно какой), то height auto будет равно нулю. Соответственно все блоки что ниже, подползают выше. А дальше идут костыли типа статического height или margin-top следующего блока за блоком с float.
Суть:
Меня это заманало. Я даже написал и пробнул сетку, которая опирается на inline-block с margin-right: -4px. Но inline block это вообще какая-то недетская жуть. Если в inline-block вкрутить ещё один inline-block, начнутся баги и фаршмаг.
Решение:
Я решил написать небольшой скрипт, который исправит недочёт флоутов.
1) Брать все элементы с css('float') - но селектора подобного нет - как их все выбрать не могу додуматься.
2) У каждого элемента с float находить массив дочерних и у каждого дочернего брать высоту.
3) Сравнивать все высоты и самую большую возвращать в блок с float, в css height.
RoverWhite: у него тухлая поддержка мобильных устройств. android только после 4.4 и iOS до 8й не поддерживаются. Я стараюсь дать поддержку всем устройствам с шириной экрана от 320 пикселей. 3и 4е айфоны и все андроиды до 14го года не поддерживаются. Это неприемлемо.
Во-первых, мне кажется проще изначально верстать по-другому, чем скриптами исправлять недочёты выбранного вами варианта верстки. Во-вторых, я понимаю конечно что это ваша вёрстка, вы в ней знаете какие элементы за что отвечают и знаете какие элементы floated, а какие - нет. Но всё же Брать все элементы с css('float') - это какая-то дичь. Вероятно, проще было бы на нужные элементы/контейнеры повесить классы, на которые можно было бы опираться. Кстати, если я не ошибаюсь, по запросу jquery equal height можно найти готовые скрипты в интернетах.
а вообще, overflow: hidden решает проблему нулевой высоты без подобных костылей...
UPD: тоже костыль, конечно, и тоже не по назначению, но он таки дает динамическую высоту "в одну строчку" средствами CSS.
нет, overflow hidden не решает проблему отсутствия высоты. У блока с float по прежнему будет height 0. А скрипт натолкнул на мысль, хоть он выбирает документ, а не элементы в нём. Тем не менее отталкиваясь от него можно поправить недочёт его селектора: $('html>*')
Никита Полевой: да там куча всякого бывает. Не представляешь что ты можешь увидеть в консоли если на мобилке откроешь imagelightbox на этом сайте))). Там накостылено двукратное приближение картники по смещениями по touchmove.
... просто это единственное, где я увидел расползание нижележащих элементов при отмене статик height... но там все просто - там позишн:абсолют с привязкой к bottom; меняем на relative, а родителю - overflow:hidden, и все встает на места без статической высоты.
Александр Х: я уже не хочу рыться, комню что на макросе в шоблоне товара float располагает галерею картинок слева и кнопки справа. Хотя там на планшетах по другому, а для мобил по ещё одному другому.
Но я щас просто новый проект верстаю. И применил сетку на inline-block. понял что лажа и исправил на float left после чего у меня полдесктопа склеилось и на мобилах пошли баги из-за потери высоты.
Никита Кит: ну, т.е., вы предлагаете просто поверить на слово? :)
Повторяю, overflow:hidden задает элементу высоту, основываясь на высоте всех его дочерних. Это работает, если и у дочерних элементов есть ненулевая высота (поэтому иногда есть смысл в самом начале всем дивам без разбора задать это свойство).
Никита Кит: во-первых, почему лажа? inline-block это вроде бы норм. Расскажите какие у вас с ним проблемы, очень интересно.
Во-вторых, по поводу float мне тоже кажется, что вы просто не учли какой-то мелочи, потому что я ни разу не видел, чтобы с ним были нерешаемые проблемы такого рода.
Если покажете пример и того и другого - было бы очень круто.
Объясню свой интерес: я использую оба варианта и никогда с ними не было никаких проблем.
Никита Полевой: нет, на самом деле как правило я боролся с флоутами либо статическими height, либо я их в какой-нибудь row закатывал, ну вообщем находились костылики. Я на самом деле флоуты за этот косяк (потеря высоты родителя) и не люблю. Вот меня это сегодня и добило.
А относительно inline-block, ну во первых margin-right: -4px - костыль против правого оффсета. Ещё помогает font-size: 0 - что уже какое-то днище.
Но вот возьми мою сетку, она у меня в реме всё ещё инлайнблокчная (https://github.com/WebKieth/beastiegrid) и попробуй сделать 3 блока, дать им всем col-lg-3, напимер.
И в один из этих блоков втусовать ещё 2 блока, которые должны делиться на col-lg-6 (те пополам, учитывая 12 колонок). И сам всё своими глазами увидишь. Уровнять эту кашу по высоте без отлицательных margin или position absolute у тебя не получится.
Александр Х: хватит меня убеждать, что float хорошие, и что с высотой всё хорошо. Если бы это было так, мой новый проект не свернулсяб в гармонь после смены свойства сетки с inline-block на float: left. И если бы overflow как-то помогал, то запихнув его сразу после float, косяк бы исчез.
Никита Кит: да я не убеждаю, в CSS - вообще все не хорошо... просто предлагаю более удобные костыли :)
А косяк "сразу" не исчезает, как правило, не потому что костыль не помогает, а потому что где-то рядом что-то еще напутано. Это же классический сюжет, когда "с чистого листа" костыль работает, а на реальном проекте - нет, хотя вроде один-в-один то же самое. А ответ, как правило, в слове "вроде". :)
Никита Кит: я понял о чем вы. Вы просто сдвигаете колонки вместо того, чтоб избавляться от промежуточных текстовых нод с пробелами; font-size: 0 не канает уже для первого уровня вложенности. Такое происходит ввиду режима inline-block: т.к. блоки строчные, все символы имеют значение, в том числе пробельные (\n\t\r в исходном коде) - они группируются в ноды, имеющие ненулевую ширину. Вот.
Для создания гридов с помощью inline-block просто убирают лишние \n\t\r. Обычно такое используют при верстке с использованием шаблонизаторов, сборщиков и прочего софта, осуществляющего генерацию кода; руками конечно это не очень приятно делать. В самом простом варианте это выглядит так.
Никита Полевой: а при чём тут сборщики или не сборщики? В итоге то всё равно мы имеем html css javascript. А значит если это возможно в gulp jade, gulp-sass, babel сделать, то я готов выслушать, ибо на сиих инструментах я сейчас и пишу)
...с точки зрения построения грида на inline-block элементах неверна, т.к. здесь много лишних пробельных символов, целых три группы: вокруг колонок, как между, так и по краям, рядом с тегами родительского контейнера. Крайние конечно не имеют значения, но выглядит это всё так.
Можно попросить CSS игнорировать текстовые переносы, тогда станет так. Текстовые ноды всё равно видны.
Как я уже говорил, достаточно в исходном коде убрать группы пробельных символов между тегами, тогда всё встанет на свои места: вот так.
Я не утверждаю, но мне кажется, что jade для этого не подходит, т.к. он whitespace-sensitive, но всё же, думаю, если вы хотите кроссбраузерно (IE8+) использовать простые и понятные гриды, есть смысл запариться с адаптацией этого подхода к используемому вами инструменту верстки. И сам тоже к сожалению не знаю, как можно уломать janejade на такое.
* - и есть селектор, который всё перебирает))))) я сделал через each(). $('body').find('*').each(function. Я не знаком с методом filter(). Как-то не приходилось)
$('body').find('*').each(function(){
var floatElem = $(this);
if(floatElem.css('float') == 'left' || floatElem.css('float') == 'right') {
var floatElemHeight = floatElem.outerHeight();
var floatElemParent = floatElem.parent();
var otherfloatElems = floatElemParent.children().not(floatElem);
var maxHeight = floatElemHeight;
if(otherfloatElems != undefined){
otherfloatElems.each(function(){
var otherfloatElemHeight = $(this).outerHeight();
if(otherfloatElemHeight > maxHeight){
maxHeight = otherfloatElemHeight;
}
floatElemParent.height(maxHeight);
})
}
}
});
Хоть и дико смотрится. Спасибо большое Александр Х и RoverWhite за помощь.
Не знаю, правда, кому решение отдать. Пожалуй Александр Х ибо его ответ пришёл раньше.
$(this).css('float') == 'left' - вот здесь одно из условий на right поправьте, эт мой глюк был (Никита Полевой в камментах об этом упоминал, но вы зачем-то стерли).
Самый кайф, что скрипт в любом случае будет работать где угодно, в любом доме будет выполнять отведённую ему роль, так что он смело п*дует на codepen в сохранёночку)))
Александр Х: Нет, отстой, нифига он не работает. Полное дно. Он выбирает то первый, то последний элемент. Даже не сравнивает 2 найденных блока, не видит общих родителей.