Двухколоночная верстка текста

    Result
    Данный топик — это не изложение азов на тему «Как сделать на своей странице две колонки с использованием div'ов и css». Передо мной стояла задача разбить монолитный текст на две колонки, подобно тому, как это делает MS Word. Стандартного тэга в css для этого не существует, поэтому пришлось немного потанцевать с бубном для решения поставленной задачи.
    Ширина колонки с текстом очень сильно влияет на простоту восприятия информации пользователем. И поэтому, учитывая нынешнюю популярность широкоформатных мониторов, разбивка текста на колонки существенно увеличивает его «читабельность».
    Для разбивки текста на колонки использовались css и немножко javascript'а. Сам алгоритм разбивки состоит всего из четырех шагов:

    Шаг 1.


    Создаем блок для текста (в примере он называется «News») и помещаем в него два блока, в которых и будет распологаться наш текст. Весь текст пока что находится в первой колонке.
    Простите за мой французский Photoshop, иллюстрации делал на быструю руку, думаю, смысл будет понятен:
    Step1

    Шаг 2.


    Первым шагом мы весь текст загнали в первую колонку Col1. Теперь javascript'ом копируем весь текст во вторую колонку (на иллюстрациях текст специально сделан градиентом, чтобы в дальнейшем можно было определить, где его верхняя часть, а где нижняя):
    Step2

    Шаг 3.


    Все тем же javascript'ом определяем нынешнюю высоту колонок Col1 и Col2. Колонке Col2 задаем отрицательный margin. Margin должен быть равен ровно половине высоты колонки. Тем самым мы поднимаем вторую колонку вверх, оставляя видимой только ее нижнюю половину:
    Step3

    Шаг 4.


    Задаем общему (желтому) блоку текста высоту, равную половине высоты колонки. Остальное обрезаем при помощи свойства overflow:hidden.
    Step4

    И смотрим результат.

    Вместо заключения


    Более сложная задача — вставить в этот текст изображение или видео, если оно попадает ровно на середину текста, или же если его ширина превышает ширину одного столбца. Согласитесь, нелепо будет выглядеть фото, если половина его располагается в нижней части первой колонки, а вторая половина — вверху второй.
    Передо мной не стояла задача реализовать такой вариант, но по идее и это решается. Все изображения должны иметь аттрибут position: absolute, а внутри колонок при помощи javascript'а необходимо будет создавать пустые элементы с размерами и координатами точно под изображение с relative position (иначе текст скроется ПОД изображениями).

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 89

      –25
      бррр! Какие цвета картинок ужасные!
        –28
        вот так вот, поставишь человеку "+" в топик

        а тебе минуса в коммент (картинки-то и правда глаза режут!) и карму.
        • UFO just landed and posted this here
            +1
            это все фашисты
        • UFO just landed and posted this here
            0
            > если у юзера отключен javascript
            и картинки
            – О-о-ох…
            +6
            Получается, на странице два блока с одинаковым текстом. Не уверен, что с т.з. SEO это гуд.

            По сути реализации. Если уж подключать JS, то можно в динамике дробить текст на две части и распихивать по блокам. На небольших объемах текста тормозить не должно.
              0
              Как разбить текст на две равные части? Тут же не символы считать надо, а его высоту при отображении в браузере. Да еще и в разных браузерах она может отличаться.
                +2
                А я не про точное деление говорил. Допустим, бить на предложения. Свои грабли у этого способа есть. Причем, не хилые. Но, имхо, лучше, чем дублировать текст на странице.
                  –3
                  А чем не устроил подсчет кол-ва символов? По-моему, можно определить их кол-во для каждого абзаца P, и после перенести несколько последних абзацев в соседний div так, чтобы суммарное кол-во символов в абзацах справа и слева было примерно одинаково.

                  При этом вторую колонку можно вообще создавать динамически и немного менять цсс, тогда решается проблема даже с параноиками с откл. js — у них просто будет одна колонка.
                    0
                    В приведенном примере пять одинаковых абзацев. Куда в таком случае должен пойти третий абзац? Здесь он делится на две части
                      0
                      Два варианта:
                      — либо бьем его на два, чтобы уравнять кол-во символов;
                      — либо оставляем в левой колонке три абзаца, а два переносим в правую (здесь логично, что в первой колонке должно быть больше текста).
                    +1
                    Вот, можно, например, так разбивать. Это далеко не оптимально, но вполне себе работает. Можно даже на onresize повесить обработчик и следить.
                    pastebin.ca/1913728
                    +2
                    Ага. И при копировании текста их тоже получается два.
                      –1
                      Я где-то про копирование сказал?
                        +3
                        Понедельник день тяжелый? :) Вы сказали про два блока, я добавил, что при выделении и копировании информация тоже дублируется.
                          0
                          Соглашусь.
                            +2
                            сегодня вторник.
                              +1
                              все равно тяжелый
                        +3
                        Насколько я понял, автор предлагает копировать текст во вторую колонку с помощью JS, то есть на SEO это не должно отразиться.
                          +3
                          Соглашусь.
                        +5
                        Скрипт не всем браузерам нужен, есть же CSS Multi-column Layout Module и в некоторых браузерах разбиение на колонки уже работает. С исключениями, но работает.
                          +11
                          работает в лисе и вебкитовских браузерах.
                          Проще подгрузить плагин для jquery (там 4 строки :))

                          $(function(){
                          	$('.wide').columnize({width:400});
                          	$('.thin').columnize({width:200});
                          });
                          
                            –7
                            и ~60kb кода скриптов
                              0
                              http://code.jquery.com/jquery-latest.min.js


                              всего 24 кб
                              И тем более jquery используется повсеместно. А если используется не он, то не проблема под свой фреймворк переписать
                                –2
                                это если стоит гзип, и поверь мне он мало где стоит, а если и есть, то выключен
                                а так, просто джиквери само 72кб + приблуда будет отдельным файлом
                                  0
                                  а что мешает использовать CDN Hosted jQuery где есть и gzip, и кеширование?
                                0
                                jQ надо брать с Google CDN. Все нормальные разрабы так делают, поэтому jQ у пользователей закеширован — либа-то очень популярная. Чем больше разрабов станут использовать CDN, тем меньше траффика будут тратить пользователи.
                                • UFO just landed and posted this here
                                    0
                                    или…
                                    и все кэширование теряет смысл)
                                      0
                                      Нет, надо брать с CDN. Иначе толку от кеша? Большинство юзает CDN, а про йандекс за пределами России не знает никто. Йандекс молодцы, но тут они дали маху.
                                      • UFO just landed and posted this here
                                          +1
                                          А, тады сорри. Я не местный, как там у вас с инетом — ничего не знаю. Если есть такая проблема, то стоит юзать Yandex, полностью согласен. Если есть много посетителей с зарубежа, то стоит фильтровать по IP и выдавать два сервера.

                                          Извините, да, я просто привык, что инет он какбе один и его дофига и он бесплатный.
                              • UFO just landed and posted this here
                                  +1
                                  это немного разные вещи
                                  большой монитор — это значит, деньги есть
                                  а браузеры — они бесплатные
                                  если человек с монитором не сильно (или вообще не)разбирается в технологиях, то будет пользоваться тем, что по умолчанию
                                  так что еслу у него Mac — это будет Safari, а если Windows — будет IE
                                +3
                                При попытки копировать, копируется 2 идентичных текста, а это существенный минус…
                                  0
                                  При изменении шрифта текст обрезается
                                    0
                                    При изменении размера шрифта, наверное?
                                    Сейчас JS рассчитан на line-height 20px, как указано в CSS, поэтому там строчка if (cmax%40>0) {cmax = cmax + 20; }
                                    20 и 40 могут стать константами и зависить от размера шрифта, это ведь просто пример.
                                    +3
                                    А что, если высота блока не кратна высоте строки?
                                    Тогда строка переноса разрежется пополам?
                                      0
                                      Ответил выше. Как раз в указанном примере высота не кратна — приходится «добавлять» еще одну строку за счет строки JS if (cmax%40>0) {cmax = cmax + 20; }, где 20 — высота строки, а 40 — удвоенная высота
                                        0
                                        Плохая распорка :) <sup> например вам все порушит. Не говоря уже о каком-то более глубоком форматировании.
                                          +1
                                          В идеале надо было бы половинным делением делать:
                                          1. Делаем скрытый див размером в 1 колонку.
                                          2. Копируем в него полтекста (бьем, к примеру, по пробелу)
                                          3. Копируем в него вторую половину
                                          4. Сравниваем высоты.
                                          5. Если надо — переразбиваем (бьем бОльшую часть пополам)

                                          Половинным делением можно за логарифмическое время разбить, думаю что будет не очень ресурсоемко.
                                            0
                                            Да, это пожалуй получше метод, чем тот, что я предложил. Не думаю, что сожрет много ресурсов, а поделит действительно ровно пополам.
                                              0
                                              На самом деле немного. Логарифмическая сложность — она «несложная» :)
                                              0
                                              Хотя над таким методом тоже думать надо, он гораздо сложнее в реализации, а значит больше вероятность ошибок в разных браузерах.
                                              Например, разбивка по пробелу. Пробел может оказаться внутри тэга html. Значит тэг нужно продублировать. А еще хуже, если пробел вообще стоит там, где текст делить нельзя, например между a и href.
                                              И все эти условия нужно проверить JS, ни о чем не забыть. И если будет много итераций, то сожрет немеряно ресурсов.
                                              P.S. Но способ все равно очень хороший)
                                                0
                                                Да, Вы правы, HTML нужно учесть. В простейшем случае просто не бить внутри тега — это несложно. Однако это может нарушить ДОМ (закрывающий тег попадет в другую колонку). Тут уже все сложнее, конечно. И для корректной реализации нужно придется идти по дереву и дублировать разорванные теги.
                                                  0
                                                  ой, сорри, вы это уже написали, а я ниже сдублировал
                                                    0
                                                    я бы не стал реализовывать такой алгоритм потому что помимо логарифмического приближения предстоит еще многократный посимвольный перебор. Сложность анализа приближается к сложности написания своего браузера, учитывая что последовательность дивов не всегда означает что они будут на экране выглядеть именно в такой последовательности.

                                                    Ну и время. Разница для больших многостраничных документов таки есть, если для генерации страницы ждать секунду или 30 секунд.

                                                    Гораздо проще использовать алгоритм из топика плюс заглушки для самых популярных тегов. Я использовал эту технологию и писал заглушку для тега имадж. Она делала несколько вещей: дописывала марджин, выравнивающий картинку под шаг шрифта, проверяла, не стоит ли картинка сразу на двух страницах и тоже увеличивала марджин, уменьшала картинку если она не вписывалась в колонку. Весил весь код, включая код оформления книжки и пагинатор 1.8 кбайт без сторонних библиотек. Быстро и просто.
                                                      0
                                                      Ну если по-умному реализовывать, то посимвольный перебор (синтаксический анализ) необходимо делать только 1 раз: предварительно разбиваем на дерево тегов (с тем же jquery это несложно), и каждое содержимое контейнера уже посимвольно анализируем, запоминая в листе дерева возможную позицию разбивки.

                                                      После этого задача сводится к обходу дерева поиском в глубину, при этом «первой половиной» будет левая часть относительно текущей вершины, а «второй половиной» — правая.

                                                      Сложность «написания своего браузера» — это уж слишком пессимистичная оценка ;) В приведенном выше алгоритме сложность сводится к дублированию всех родителей текущей вершины для закрытия тегов или их открытия.

                                                      Наверное, на досуге таки реализую… может быть в качестве плагина к тому же жквери.

                                                      Однако соглашусь с тем, что див на экране может находиться не совсем там где он есть в коде — но тут придется таки принебречь некоторыми возможностями, вроде position: absolute; или всяческих манипуляций с маргинами, иначе тогда двухколоночная верстка смысла особого не имеет. Все же мы ее хотим применить с обычным текстом (streamLayout, если так можно выразиться).
                                                  0
                                                  если бьёте внутри абзаца или <div>'а — надо в первой колонке закрыть </p> или </div>
                                                  а во второй надо открыть новый, с теми же стилями, что и первый был
                                                  то есть когда бьёте, надо будет ещё отследить открывающий тэг
                                            0
                                            Разделение текста на 2 колонки на perl с сохранением базового форматирования:
                                            domdev.ru/post/detail/10/
                                              +1
                                              Идея интересная. Но, можно предположить, найдутся какие-то маргинальные случаи, когда будет виден кусочек строки.
                                                +8
                                                Стандартного тэга в css для этого не существует, поэтому пришлось немного потанцевать с бубном для решения поставленной задачи.

                                                Прими небольшую поправку по тексту твоего поста: в css тег — это сущность, которой можно задавать свойства, ты, в свою очередь, видимо хотел сказать про свойство.

                                                По поводу самого метода разделения текста — мне кажется, что этот метод является решением лишь для одного расклада требований, не больше, следовательно полезность его приближается к 1% случаев.

                                                Эээх, вот в таких ситуациях и понимаешь всю мощь CSS3.0, где можно было бы написать одну строчку column-count: 2; и ничего более. Кому интересно — ссылка на источник w3c
                                                  +9
                                                  Держите готовый плагин Columnizer jQuery Plugin. На странице представлено много демок, если лень все смотреть, то можете посмотреть демо с текстом и демо с картинками. Кстати, 2 колонки на главной странице плагина — это тоже результат его применения.
                                                    0
                                                    В демке с картинками вторая колонка начитается с точки почему то.
                                                      0
                                                      ff 3.6.8, вторая колонка начинается с «timeam sapientem eos».
                                                        0
                                                        В каждом браузере по разному начинается. Да и с картинками бока какие-то, если уж писали с учетом картинок, то можно было и получше реализовать. Хотя для разработчика гораздо проще — скопировал код и готово)
                                                          0
                                                          судя по тому что в опере и хроме окрашиваются синим цветом разные блоки текста, сделаю предположение, что алгоритм похож на алгоритм, предложенный 0lympian выше.
                                                    +2
                                                    стоит тогда для людей с отключённым JS делать первую колонку изначально растянутую на всю ширину блока. А если включён JS то уже им уменьшать колонку в 2 раза и создавать вторую, дабы текст при отключённом скрипте не выглядел узким
                                                      +4
                                                      Решение тривиальное, непонятно зачем писать об этом
                                                        +1
                                                        App Engine Error


                                                        Over Quota
                                                        This Google App Engine application is temporarily over its serving quota. Please try again later.
                                                          0
                                                          да я уже и не думал, что пост на главную пробьется
                                                          +3
                                                          column-count: 2;
                                                            –1
                                                            Ага, осталось только дождаться, когда IE и Opera будут ассоциироваться у пользователей со словом «вирус»…
                                                            0
                                                            Еще с выделением проблемы: попробуйте выделить немного текста в первой колонке, потом нажмите Shift+вниз — обе колонки начнут прокручиваться вниз и вылезет скрытый текст (Chrome, Safari). В FF прокрутки не будет, но выделение поползет в скрытую область, а не на следующую колонку, как бы я ожидал. В Opera и IE Shift+вниз не работают.

                                                            Ну и +1 за то, что при копировании мышкой скопированный текст дублируется — это плохо.
                                                              +2
                                                              Верните картинки!
                                                                +1
                                                                «Данный топик — это не изложение азов на тему, куда не нужно заливать картинки...»
                                                                  0
                                                                  Пожалуй, стоит поизучать азы)))
                                                                  Я уже и забыл про этот пост, никак не ожидал, что он два дня спустя на главную выберется
                                                                0
                                                                Способ годится лишь как упражнение для студентов первого курса.
                                                                В реальных проектах использовать вряд ли порекомендую.
                                                                  0
                                                                  альтернатива?
                                                                  +2
                                                                  что-то у меня картинки не отображаются…
                                                                    –1
                                                                    недавно написал код для разбиения DL-списка на две колонки, ничего два раза копировать не требуется, решение на js
                                                                      –3
                                                                      КАРТИНКИ МНЕ ЗАПИЛИЛ!
                                                                        +1
                                                                        Распилил и откатил.
                                                                        +1
                                                                        GAE не выдержал хабраэффекта.
                                                                          +1
                                                                          Тестировал как-то хабраэффект на GAE. Одна картинка размером 17kb (на главной), дала трафика чуть больше чем на 1Gb.
                                                                          +1
                                                                          Стандартного тэга в css для этого не существует
                                                                          Неудивительно — в CSS нет тегов. Кстати, когда-то в Netscape для этой цели придумали тег MULTICOL.
                                                                            0
                                                                            С Javascript не интересно, будет куда восхитительней сделать это на HTML+CSS. Уже не одно копье сломал, пытаясь этого добиться.
                                                                              –1
                                                                              В принципе, алгоритм все тот же. Сделал за 10 минут без проблем, ток почему-то в Опере лажу выдает. Chrome, ff и IE(!!!) работает отлично.
                                                                              Я не большой мастер верстки, сейчас попробую устранить, но не обещаю. Получится — выложу…
                                                                                +1
                                                                                Я не большой мастер верстки, сейчас попробую

                                                                                А зачем тогда «небольшому мастеру вёрстки» писать топик с решением проблемы, в которой он не разбирается и даже не знаком с модулем Multi-column?
                                                                            • UFO just landed and posted this here
                                                                                0
                                                                                Меня одного передергивает от justify на первом скриншоте?

                                                                                А про идею — практическое применение с мультимедиа контентом убьет верстку, как автор, впрочем, и заметил в конце поста. Но предложение применить JS для исправления косяков верстки меня вгоняет в ступор.

                                                                                Увидел, что плагин для jQ уже предложили. Дважды. Повторяться не буду, лишь соглашусь.
                                                                                  0
                                                                                  а почему бы не делать это так как это делают в бумажных изданиях? я имею ввиду руками. имхо, луче чем привязывать к килобайтной страничке гигабайтный скрипт который делает это автоматом…
                                                                                    0
                                                                                    Какае-то выдуманная проблема и попытки ее решить.
                                                                                    Я бы не читал текст разбитый таким образом.
                                                                                      +1
                                                                                      Вёрстка в узкие колонки это наследие печати (газет и журналов). На экране она нафиг не упала.
                                                                                      Максимум допустимоси — если высота колонки не превышает высоту видимой области. Если мне нужно три раза проскролить вверх-вниз экран — читать жутко неудобно.
                                                                                        0
                                                                                        о ajax и серверсайд никто не подумал.
                                                                                        что вы клиента мучаете, как в корейских сайтах. 160 кб жабаскрипта из которого исполняется 1%.
                                                                                          0
                                                                                          да и еще — дико извиняюсь, но вообще-то уже появились вебсокеты.
                                                                                            0
                                                                                            в корее никто не считает килобайтов, поскольку широкополосный интернет там распространился почти на десять лет раньше, чем у нас
                                                                                            +1
                                                                                            Не хочу показаться неадекватным — не проще ли вставлять в текст специальные метки (например, [p]) по которым резать текст на колонки яваскриптом?
                                                                                            В любом JS-текстовом редакторе можно наглядно определить где разместить такой псевдо-тег.
                                                                                            Ну и не задача это браузера разбивать текст на колонки. а задача верстальщика (редактора текстов), т.к. только он может оценить полученный результат с точки зрения правильности

                                                                                            Only users with full accounts can post comments. Log in, please.