Создание 3D меню ресторана на CSS

Использование CSS 3D transform, может добавить дополнительный реализм к обычным веб-элементам. Мы работали над разработкой простых сайтов ресторанов и придумали интересное 3D меню ресторана (реальное меню, не "веб" меню). Результат - шаблон веб-сайта ресторана, в котором присутствует наше 3D меню ресторана.

Сложность

Так как эта тестовый демонстрационный пример, меню займет много места на странице, несмотря на то, что мы сделаем его адаптивным с помощью медиа запросов. Также настроим дополнительные стили для браузеров, которые не поддерживают 3D CSS transform rotate.

HTML разметка

Наша структура будет состоять из основного контейнера с классом rm-container и оболочкой внутри. Оболочка будет иметь три панели. Изначально, отображаем меню в свернутом состоянии, это будет контейнер с классом rm-cover.

<div id="rm-container" class="rm-container">
    <div class="rm-wrapper">
        <div class="rm-cover"></div>
        <div class="rm-middle"></div>
        <div class="rm-right"></div>
    </div><!-- /rm-wrapper -->
</div><!-- /rm-container -->

Для контейнеров rm-cover и rm-right зададим две стороны, переднюю и заднюю:

<div class="rm-front">

   <div class="rm-content">
      <!-- Some content -->
   </div><!-- /rm-content -->
   
</div><!-- /rm-front -->

<div class="rm-back">

   <div class="rm-content">
      <!-- Some content -->
   </div><!-- /rm-content -->

   <div class="rm-overlay"></div>

</div><!-- /rm-back -->

Добавим градиент для элементов меню, чтобы придать больше реализма. Обратите внимание, что последней панели, будет пустая передняя сторона.

У средней панели, оболочка будет отличаться:

<div class="rm-inner">

   <div class="rm-content">
      <!-- Some content -->
   </div><!-- /rm-content -->

   <div class="rm-overlay"></div>

</div><!-- /rm-inner -->

Контент будет состоять из некоторых текстовых элементов, такие как списки и заголовки:

<div class="rm-content">

   <h4>Appetizers</h4>

   <dl>
      <dt>Bella's Artichokes</dt>
      <dd>Roasted artichokes with chipotle aioli and cream cheese</dd>

      <dt><a href="http://herbivoracious.com/2011/11/crostini-with-young-pecorino-grilled-figs-and-arugula-mint-pesto-recipe.html" class="rm-viewdetails" data-thumb="images/1.jpg">Green Love Crostini</a></dt>
      <dd>Crostini with young pecorino, grilled figs and arugula & mint pesto</dd>
      
      <dt>Focaccia di Carciofi</dt>
      <dd>Artichoke focaccia with fresh thyme</dd>

      <!-- ... -->
   </dl>

   <h4>Salads & More</h4>
   
   <dl>
      <!-- ... -->
   </dl>

</div><!-- /rm-content -->

Взгляните на ссылку с классом rm-viewdetails и атрибутом “data-thumb”. Мы будем использовать их в качестве контента для модального отображения, которое появляется при нажатии:

<div class="rm-modal">
   <div style="background-image: url('/images/1.jpg')" class="rm-thumb"></div>
   <h5>Green Love Crostini</h5>
   <p>Crostini with young pecorino, grilled figs and arugula & mint pesto</p>
   <a href="http://herbivoracious.com/2011/11/crostini-with-young-pecorino-grilled-figs-and-arugula-mint-pesto-recipe.html">See the recipe</a>
   <span class="rm-close-modal">x</span>
</div>

CSS

Необходимо сделать все элементы плавающими, поэтому мы зададим основному контейнеру ширину в 1% и добавим CSS perspective:

.rm-container { 
    width: 33%; 
    height: 700px; 
    max-width: 370px; 
    margin: 0 auto 40px auto; 
    position: relative; 
    perspective: 1600px; 
    color: #2a323f; 
}

Для оболочки и ее блоков, зададим абсолютное расположение, 100% ширину и высоту:

.rm-wrapper, 
.rm-wrapper > div { 
    width: 100%; 
    height: 100%; 
    left: 0; 
    top: 0; 
    position: absolute; 
    text-align: center; 
    transform-style: preserve-3d; 
}

Так как мы будем работать с 3D CSS perspective, необходимо чтобы значение преобразования этих элементов было preserve-3d.

Обложка должна иметь более высокий z-index, по сравнению с другими панелями. Зададим задержку закрытия 3D меню ресторана. Переход в открытое состояние будет иметь другое значение задержки, мы вернемся к этому позже:

.rm-wrapper .rm-cover { 
    z-index: 100; 
    transform-origin: 0% 50%; 
    transition-delay: 0.2s; 
}

У средней части будет самый низкий z-index. Добавим для неё небольшую тень:

.rm-wrapper .rm-middle { 
    z-index: 50; 
    box-shadow: 0 4px 10px rgba(0,0,0,0.7); 
}

У правой части z-index будет выше, чем у средней части, но ниже чем у обложки.

.rm-wrapper .rm-right { 
    z-index: 60; 
    transform-origin: 100% 50%; 
    transition-delay: 0s; 
}

У внутренних блоков с классами rm-front, rm-back и rm-inner, будет фоновая текстура в виде бумаги, а также установим для них тень, которая моделирует многострочную декоративную рамку:

.rm-wrapper > div > div { 
    background: #fff url(../images/white_paperboard.jpg); 
    width: 100%; 
    height: 100%; 
    position: absolute; 
    padding: 30px; 
    box-shadow:  
        inset 0 0 0 16px #fff,  
        inset 0 0 0 17px #e6b741,  
        inset 0 0 0 18px #fff,  
        inset 0 0 0 19px #e6b741,  
        inset 0 0 0 20px #fff,  
        inset 0 0 0 21px #e6b741; 
}

Теперь, давайте добавим важные 3D свойства. Для обратной стороны основного контейнера, добавим свойство backface-visibility: hidden:

.rm-container .rm-front, 
.rm-container .rm-back { 
    backface-visibility: hidden; 
}

Повернем её на 180 градусов:

.rm-container .rm-back { 
    transform: rotateY(-180deg); 
}

Добавим полупрозрачный css градиент:

.rm-overlay { 
    position: absolute; 
    width: 100%; 
    height: 100%; 
    top: 0; 
    left: 0; 
    pointer-events: none; 
    background: linear-gradient(to right, rgba(0,0,0,0) 0%, rgba(0,0,0,0.05) 100%); 
}

Для средней панели, отобразим css градиент в обратную сторону:

.rm-middle .rm-overlay { 
    background: linear-gradient(to right, rgba(0,0,0,0) 64%, rgba(0,0,0,0.05) 100%); 
}

Зададим дополнительный отступ для блока с контентом:

.rm-content { 
    padding: 20px; 
}

Модальное наложение будет невидимым, мы установим непрозрачность в 0 и передвинем его по оси Z:

.rm-modal { 
    position: absolute; 
    z-index: 10000; 
    width: 120%; 
    margin-left: -10%; 
    top: 50%; 
    padding: 40px; 
    background: #fff url(../images/white_paperboard.jpg); 
    box-shadow:  
        inset 0 0 0 16px #fff,  
        inset 0 0 0 17px #e6b741,  
        inset 0 0 0 18px #fff,  
        inset 0 0 0 19px #e6b741,  
        inset 0 0 0 20px #fff,  
        inset 0 0 0 21px #e6b741, 
        0 4px 20px rgba(0,0,0,0.4); 
    opacity: 0; 
    pointer-events: none; 
    transform: translateZ(1000px); 
}

Идея состоит в том, чтобы показать модальное наложение, когда мы щелкаем по одной из ссылок в меню.

Давайте добавим переходы и дополнительные классы для открытия 3D меню.

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

.rm-wrapper, .rm-wrapper > div { transition: all 0.6s ease-in-out; }

У модального наложения также будет переход:

.rm-modal { 
    transition:  
        transform 0.6s ease-in-out, 
        opacity 0.6s ease-in-out; 
}

Класс rm-open должен вызывать 3D меню при нажатии по ссылке "Открыть меню". Этот класс будет добавлен при помощи JavaScript.

Всем дочерним элементам оболочки, добавим тень:

.rm-container.rm-open .rm-wrapper > div { 
    box-shadow: 0 4px 5px -3px rgba(0,0,0,0.6); 
}

Повернем обложку (без задержки) на -180 градусов по оси Y.

.rm-container.rm-open .rm-cover { 
    transform: rotateY(-180deg); 
    transition-delay: 0s; 
}

Правую часть повернем на 180 градусов, но здесь мы добавим задержку в 0.2 с, чтобы обложка открылась немного раньше:

.rm-container.rm-open .rm-right { 
    transform: rotateY(180deg); 
    transition-delay: 0.2s; 
}

При нажатии по одному из пунктов меню, которые является ссылками, мы добавим класс rm-in к контейнеру и переместим оболочку вниз по оси Z:

.rm-container.rm-in .rm-wrapper { 
    transform: translateZ(-500px); 
}

Обложка и правая панель будут повернуты в направлении к внутреннему блоку:

.rm-container.rm-in .rm-cover { 
    transform: rotateY(-150deg); 
} 
  
.rm-container.rm-in .rm-right { 
    transform: rotateY(150deg); 
}

Для этого, установим задержку в 0 секунд:

.rm-container.rm-in .rm-cover,  
.rm-container.rm-in .rm-right, 
.rm-container.rm-nodelay .rm-right { 
    transition-delay: 0s; 
}

Класс rm-nodelay является дополнительным классом, который мы будем использовать для правой части меню, когда мы закрываем модальное наложение. Помните, мы установили для него задержку при открытии меню.

Перейдем к медиа запросам для мобильных устройств. Для начала просто меняем размеры оболочки:

@media screen and (max-width: 1110px) { 
    .rm-container { 
        height: 800px; 
    } 
}

Так как мы сделали плавающую оболочку, установим для неё большую высоту, чтобы поместился весь текст.

960px достаточно, чтобы отображать развернутое меню с возможностью прокрутки. Для этого мы просто зададим 100% ширину и автоматическую высоту:

@media screen and (max-width: 960px) { 
  
    .rm-container { 
        width: 100%; 
        height: auto; 
        max-width: 460px; 
    }

Все внутренние контейнеры будут иметь относительное расположение, зададим для них 100% ширину и автоматическую высоту:

.rm-wrapper,  
.rm-wrapper > div, 
.rm-wrapper > div > div { 
    position: relative; 
    width: 100%; 
    height: auto; 
}

Добавим дополнительные отступы для блока с контентом:

.rm-wrapper > div > div{ 
    margin-bottom: 10px; 
    box-shadow:  
        inset 0 0 0 16px #fff,  
        inset 0 0 0 17px #e6b741,  
        inset 0 0 0 18px #fff,  
        inset 0 0 0 19px #e6b741,  
        inset 0 0 0 20px #fff,  
        inset 0 0 0 21px #e6b741, 
        0 3px 5px rgba(0,0,0,0.2); 
}

Удалим вращения:

.rm-container .rm-back, 
.rm-container.rm-open .rm-cover, 
.rm-container.rm-open .rm-right { 
    transform: rotateY(0deg); 
}

Установим фиксированную позицию для элемента rm-modal, так, чтобы он находился сверху при прокрутке:

.rm-container .rm-modal { 
    position: fixed; 
    width: 80%; 
    top: 100px; 
    left: 50%; 
    margin: 0 0 0 -40%; 
    transform: translateZ(0px); 
    transition: opacity 0.6s ease-in-out 0s; 
}

Когда мы нажимаем на пункт меню, появляется модальное наложение:

.rm-container.rm-in .rm-cover, 
    .rm-container.rm-in .rm-right, 
    .rm-container.rm-in .rm-wrapper { 
        transform: rotateY(0deg); 
        transition-delay: 0s; 
    } 
}

Для браузеров, которые не поддерживают 3D CSS transforms, мы будем использовать почти такое же моделирование, но с добавлением медиа запросов. Для этого мы будем использовать Modernizr.

JavaScript

Начнем с кэширования элементов:

 // основной контейнер 
var $container = $( '#rm-container' ),                       
    // обложка, левая и правая панели 
    $cover = $container.find( 'div.rm-cover' ), 
    $middle = $container.find( 'div.rm-middle' ), 
    $right = $container.find( 'div.rm-right' ), 
    // открытие и закрытие элементов 
    $open = $cover.find('a.rm-button-open'), 
    $close = $right.find('span.rm-close'), 
    // ссылки для каждого рецепта (фотография и детали)
    $details = $container.find( 'a.rm-viewdetails' ),

Инициализируем событий открытия/закрытия меню ресторана, чтобы показать дополнительные детали каждого элемента:

init = function() { 
  
        initEvents(); 
  
    }, 
initEvents = function() { 
  
    $open.on( 'click', function( event ) { 
  
        openMenu(); 
        return false; 
  
    } ); 
  
    $close.on( 'click', function( event ) { 
  
        closeMenu(); 
        return false; 
  
    } ); 
  
    $details.on( 'click', function( event ) { 
  
        $container.removeClass( 'rm-in' ).children( 'div.rm-modal' ).remove(); 
        viewDetails( $( this ) ); 
        return false; 
  
    } ); 
      
},

Чтобы открыть/закрыть меню, мы будем соответсвено добавлять/удалять класс, rm-open из $container..

Обратите внимание, что в конце мы также удаляем классы rm-nodelay и rm-in. Это дополнительные классы для отображения деталей пунктов меню:

openMenu = function() { 
  
    $container.addClass( 'rm-open' ); 
  
}, 
closeMenu = function() { 
  
    $container.removeClass( 'rm-open rm-nodelay rm-in' ); 
  
},

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

viewDetails = function( recipe ) {
 
    var title = recipe.text(),
        img = recipe.data( 'thumb' ),
        description = recipe.parent().next().text(),
        url = recipe.attr( 'href' );
 
    var $modal = $( '<div class="rm-modal"><div class="rm-thumb" style="background-image: url('/ + img + ')"></div><h5>' + title + '</h5><p>' + description + '</p><a href="/%27%20+%20url%20+%20%27">See the recipe</a><span class="rm-close-modal">x</span></div>' );
 
    $modal.appendTo( $container );
 
    var h = $modal.outerHeight( true );
    $modal.css( 'margin-top', -h / 2 );
 
    setTimeout( function() {
 
        $container.addClass( 'rm-in rm-nodelay' );
 
        $modal.find( 'span.rm-close-modal' ).on( 'click', function() {
 
            $container.removeClass( 'rm-in' );
 
        } );
     
    }, 0 );
 
};

ДЕМО СКАЧАТЬ Перевод статьи 3D Restaurant Menu Concept

 

Тэги: transition3D transform

Вход

Уважаемый пользователь! Мы обнаружили, что вы используете AdBlock и вынуждены скрыть часть материалов на нашем сайте. Siteacademy существует и развивается за счет доходов от рекламы. Просим внести наш сайт в список исключений или отключить Блокировщик рекламы на нашем сайте.