Как сделать плавный изгиб - переход от красной части меню к чёрной

73
06 марта 2022, 00:00

Это можно сделать используя CSS? Или придётся картинкой делать?

Answer 1

Вот, если угодно, на градиентах:

.top, .bottom { 
  height: 22.5px; 
  --r: 30px; 
  --g: radial-gradient( 
          circle at calc(50% - calc(var(--o) * 50%)) 0,  
          var(--c1),  
          var(--c1) calc(50% - var(--r)),  
          #0000 calc(2px + calc(50% - var(--r)))), 
       radial-gradient( 
          circle at calc(50% - calc(calc(var(--o) * var(--r)))) calc(50% + calc(var(--o) * 80%)),  
          var(--c1),  
          var(--c1) calc(var(--r) - 1px),  
          var(--c2) calc(var(--r) + 1px)); 
} 
 
.top { 
  --c1: red; 
  --c2: black; 
  --o: 0.98; 
  background: var(--g); 
} 
 
.bottom { 
  --c1: black; 
  --c2: red; 
  --o: -0.98; 
  background: var(--g); 
}
<div class="top"></div> 
<div class="bottom"></div>

Answer 2

Решение на чистом CSS

Правда совсем небольшой дефект виден, но это уже если всматриваться. Думаю, что пользователи сайта этого как правило не делают :) Но зато есть градиент и вся задумка решена на 99,9%.

UPD Улучшил ответ. Теперь дефект практически не заметен. А также учёл замечания @Alexandr_TT и @ArtemGorlachev и добавил ещё дополнительно адаптивный вариант. Адаптивность конечно получилась не совсем та, что хотелось, но постараюсь доработать.

.nav { 
  position: relative; 
  overflow: hidden; 
  height: 80px; 
  width: 100%; 
  margin: 0 auto; 
  margin-bottom: 10px; 
} 
 
.nav__left { 
  position: relative; 
  overflow: hidden; 
  float: left; 
  height: 80px; 
  width: 49%; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
.nav__right { 
  position: relative; 
  overflow: hidden; 
  float: right; 
  height: 80px; 
  width: 49%; 
  background: linear-gradient(to bottom, gray, black); 
} 
 
.transition { 
  position: absolute; 
  overflow: hidden; 
  top: 0; 
  left: 0; 
  right: 0; 
  margin: 0 auto; 
  height: 80px; 
  width: 180px; 
} 
 
.transition__red { 
  position: absolute; 
  left: 0; 
  top: 0; 
  height: 80px; 
  width: 100px; 
  background: linear-gradient(to bottom, gray, black); 
} 
 
.transition__red:after { 
  content: ""; 
  display: block; 
  height: 80px; 
  width: 100px; 
  border-radius: 0px 90px 0px 0px / 0px 100% 0px 0px; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
.transition__black { 
  position: absolute; 
  right: 0; 
  top: 0; 
  height: 80px; 
  width: 100px; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
.transition__black:after { 
  content: ""; 
  display: block; 
  height: 80px; 
  width: 100px; 
  border-radius: 0 0 0 100% / 0 0 0 100%; 
  background: linear-gradient(to bottom, gray, black); 
} 
 
.transition__clear { 
  position: absolute; 
  left: -56px; 
  top: 0px; 
  width: 170px; 
  height: 80px; 
  border-radius: 0 100% 0 0; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
.transition__clear:after { 
  content: ""; 
  display: block; 
  position: absolute; 
  top: 0px; 
  right: 0px; 
  left: -151px; 
  width: 300px; 
  height: 80px; 
  border-radius: 0% 60% 0% 0%; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
span { 
  margin: 0 20px; 
  color: white; 
  line-height: 80px; 
  font-size: 20px; 
  font-family: monospace; 
} 
 
.nav__left span { 
  float: left; 
} 
 
.nav__right span { 
  float: right; 
} 
 
.block__left { 
  position: relative; 
  overflow: hidden; 
  float: left; 
  height: 80px; 
  width: 49%; 
  border-radius: 5px; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
.block__right { 
  position: relative; 
  overflow: hidden; 
  float: right; 
  height: 80px; 
  width: 49%; 
  border-radius: 5px; 
  background: linear-gradient(to bottom, gray, black); 
}
<div class="nav"> 
  <div class="nav__left"><span>А-ля Left</span></div> 
  <div class="nav__right"><span>А-ля Right</span></div> 
  <div class="transition"> 
    <div class="transition__black"> 
    </div> 
    <div class="transition__red"> 
    </div> 
    <div class="transition__clear"></div> 
  </div> 
</div> 
<div class="block__left"></div> 
<div class="block__right"></div>

Адаптивный вариант:

body, 
html { 
  margin: 0; 
  padding: 0; 
} 
 
.nav { 
  position: relative; 
  overflow: hidden; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  width: 100%; 
  margin: 0 auto; 
  margin-bottom: 10px; 
} 
 
.nav__left { 
  position: relative; 
  overflow: hidden; 
  float: left; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  width: 49%; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
.nav__right { 
  position: relative; 
  overflow: hidden; 
  float: right; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  width: 49%; 
  background: linear-gradient(to bottom, gray, black); 
} 
 
.transition { 
  position: absolute; 
  overflow: hidden; 
  top: 0; 
  left: 0; 
  right: 0; 
  margin: 0 auto; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  width: 180px; 
} 
 
.transition__red { 
  position: absolute; 
  left: 0; 
  top: 0; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  width: 100px; 
  background: linear-gradient(to bottom, gray, black); 
} 
 
.transition__red:after { 
  content: ""; 
  display: block; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  width: 100px; 
  border-radius: 0px 90px 0px 0px / 0px 100% 0px 0px; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
.transition__black { 
  position: absolute; 
  right: 0; 
  top: 0; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  width: 100px; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
.transition__black:after { 
  content: ""; 
  display: block; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  width: 100px; 
  border-radius: 0 0 0 100% / 0 0 0 100%; 
  background: linear-gradient(to bottom, gray, black); 
} 
 
.transition__clear { 
  position: absolute; 
  left: -56px; 
  top: 0px; 
  width: 170px; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  border-radius: 0 100% 0 0; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
.transition__clear:after { 
  content: ""; 
  display: block; 
  position: absolute; 
  top: 0px; 
  right: 0px; 
  left: -151px; 
  width: 300px; 
  height: 100vh; 
  min-height: 80px; 
  max-height: 30vh; 
  border-radius: 0% 60% 0% 0%; 
  background: linear-gradient(to bottom, red, darkred); 
} 
 
span { 
  margin: 0 20px; 
  color: white; 
  line-height: 80px; 
  font-size: 20px; 
  font-family: monospace; 
} 
 
.nav__left span { 
  float: left; 
} 
 
.nav__right span { 
  float: right; 
}
<div class="nav"> 
  <div class="nav__left"><span>А-ля Left</span></div> 
  <div class="nav__right"><span>А-ля Right</span></div> 
  <div class="transition"> 
    <div class="transition__black"> 
    </div> 
    <div class="transition__red"> 
    </div> 
    <div class="transition__clear"></div> 
  </div> 
</div>

Answer 3

Вот так это делается!

Если требуются подробности - спрашивайте - поясню со скринами

Сделал меню и адаптировал его в codepen ... codepen.io

* { 
  box-sizing: border-box; 
} 
 
ul { 
  display: flex; 
  list-style: none; 
  position: relative; 
  height: 45px; 
  width: 480px; 
  align-items: center; 
  background: #b83d2e; 
} 
 
li { 
  width: 100%; 
} 
 
li a { 
  color: #fff; 
  font-size: ; 
  text-decoration: none; 
} 
 
.svg { 
  position: absolute; 
  left: 100%; 
  top: 0; 
  width: 170px; 
  height: 45px; 
  overflow: hidden; 
}
<ul> 
  <li> 
    <a href="">ссылка №1</a> 
 
  </li> 
  <li> 
    <a href="">ссылка №2</a> 
 
  </li> 
  <li> 
    <a href="">ссылка №3</a> 
 
  </li> 
  <li> 
    <a href="">ссылка №4</a> 
    <div class="svg"> 
      <svg width="170mm" height="45mm" xmlns="http://www.w3.org/2000/svg"> 
           <g transform="translate(-1,-251.95859)"> 
           <path d="m1.00005 252.20983-1.511905 44.79017 170.46726-0.56696c-28.27272-4.30384-41.00151-28.7266-55.86311-34.64265-27.001632-10.74869-52.971732-10.13029-113.04224-9.58056z" fill="#b83d2e"/> 
      </g> 
      </svg> 
    </div> 
  </li> 
</ul>

Так же можно не выводить код svg в html и можно в этом случае сделать так :

ul, 
li, 
a { 
  list-style: none; 
  text-decoration: none; 
  font-size: 20px; 
  margin: 0; 
  padding: 0; 
} 
 
ul { 
  display: flex; 
  align-items: center; 
  width: 480px; 
  height: 45px; 
  background: #b03023; 
  position: relative; 
} 
 
ul li { 
  width: 100%; 
  text-align: center; 
} 
 
ul li a { 
  color: #fff; 
} 
 
.svg { 
  display: block; 
  width: 164px; 
  height: 45px; 
  position: absolute; 
  left: 100%; 
  top: 0; 
  background-image: url("data:image/svg+xml,%3Csvg width='164.42mm' height='44.790192mm' version='1.1' viewBox='0 0 164.42 44.790192' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform='translate(-2,-252.20981)'%3E%3Cpath d='M 164.42,296.811 C 108.15057,294.33073 97.997565,253.78942 62.744187,252.96577 L 0,252.20981 0.18899041,297 Z' fill='%23b03023'/%3E%3C/g%3E%3C/svg%3E%0A"); 
  background-size: 100% 100%; 
}
<ul> 
  <li> 
    <a href="#">Ссылка №1</a> 
  </li> 
  <li> 
    <a href="#">Ссылка №2</a> 
  </li> 
  <li> 
    <a href="#">Ссылка №3</a> 
  </li> 
  <div class="svg"></div> 
</ul>

Answer 4

Решение №2 на чистом CSS

Самое короткое настолько, насколько это возможно. Короче не придумаешь.

Полностью адаптивно на все 100%.

Работает во всех браузерах без исключений.

.nav { 
  display: inline-block; 
  position: relative; 
  overflow: hidden; 
  width: 100%; 
} 
.adaptive { margin-top: 15%; } 
.nav__wrp { 
  position: absolute; 
  top: 0; 
  bottom: 0; 
  left: 0; 
  right: 0; 
} 
.nav__left, .nav__right { 
  position: relative; 
  overflow: hidden; 
  height: 100%; 
  width: 50%; 
} 
.nav__left { float: left; background: linear-gradient(to bottom, red, darkred); } 
.nav__right { float: right; background: linear-gradient(to bottom, gray, black); } 
.nav__left:before, .nav__right:before, .nav__left:after, .nav__right:after { 
  content: ""; 
  display: block; 
  position: absolute; 
  height: 100%; 
  width: 103%; 
  top: 0; 
} 
.nav__left:before { right: 0; background: linear-gradient(to bottom, gray, black); } 
.nav__right:before { left: 0; background: linear-gradient(to bottom, red, darkred); } 
.nav__left:after { right: -3%; background: linear-gradient(to bottom, red, darkred); border-radius: 0 70% 0 0; } 
.nav__right:after { left: -3%; background: linear-gradient(to bottom, gray, black); border-radius: 0 0 0 70%; }
<div class="nav"> 
<div class="adaptive"></div> 
<div class="nav__wrp"><div class="nav__left"></div><div class="nav__right"></div></div> 
</div>

Answer 5

Это можно сделать используя CSS?

Да, можно.

Но лучше делать такое картинкой и подкладывать в нужное место через background-image или в виде элемента с абсолютным позиционированием. (например через псевдоэлемент before).

На CSS такое тоже можно сделать, но вы либо напишите пару страниц кода с border-radius, либо уйдете в полигоны/пути и SVG графику.

Первое решение (чистый CSS) - это ненужное награмождение и усложнение кода.

Второе решение (clip-path + SVG) - это по сути замена PNG картинки на SVG картинку (в конкретно вашем случае).

В огромном CSS, clip-path и SVG есть смысл только для создания красивых анимаций и переходов. (Ниже приложил пример правильного использования.)

Хотите доказательств?

Опуститесь ниже и посмотрите другие варианты решения. Умные люди изощряются с ними и уже почти готовы друг друга на ножи посадить, выясняя чей CSS лучше.

А теперь представьте что Вам нужно не просто сделать такое, но и в дальнейшем обслуживать. Причем обслуживать будете не вы, а условный "Леха стажер", которого руководство нашло на фрилансе.

Желание блеснуть инструментарием подходит только для профессиональных сообществ вроде этого. В реальной разработке нужно использовать максимально простой вариант из решающих задачу. Это сокращает затраты, понижает порог вхождения в ваш проект, делает дальнейшее обслуживание удобным.

Правильное применение css полигонов и SVG

Если интересно почитать про полигоны и их правильное применение в css, вот пример где использование этих инструментов оправдано:

Создаем крутые фигуры с помощью Clip-Path и разбиваем привычную боксовую модель

Если интересно SVG и все что связано с его анимированием: https://svg-art.ru/

Создатель сайта тут сидит и регулярно дает ответы на вопросы. Профиль: @Alexandr_TT

Answer 6

Приложение полностью адаптивно.

Работает во всех браузерах, включая MS Edge

Цвет, градиенты максимально приближены к оригиналу.

.container { 
width:100%; 
height:100%; 
} 
.partBlack { 
fill:url(#LGblack); 
} 
.partRed { 
fill:url(#LGred); 
} 
.textRed { 
font-size:72px; 
fill:white; 
} 
 
.textBlack { 
font-size:72px; 
fill:white; 
}
<div class="container"> 
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"  viewBox="0 0 1388 868" preserveAspectRatio="xMinYMin meet"> 
    
   <defs> 
    <linearGradient id="LGred" x2="0%" y2="100%"> 
	  <stop offset="0%" stop-color="#C14A3A"/> 
	   <stop offset="100%" stop-color="#A31D12"/> 
	</linearGradient>   
       <linearGradient id="LGblack" x2="0%" y2="100%"> 
	  <stop offset="0%" stop-color="#444444"/> 
	   <stop offset="100%" stop-color="#202020"/> 
	</linearGradient>	 
   </defs> 
   <rect class="partBlack" x="4" y="260" width="1388" height="165"/> 
    
   <path class="partRed"  d="M3.4 259.4H507.1c22.7 0 45.3 4.2 67.5 9.2 26.7 6 52.9 14.2 78.2 24.6 13.1 5.4 25.5 12.3 37.7 19.5 12.1 7.1 23.8 15.1 35.1 23.4 12.1 9 23.1 19.4 35.1 28.6 11.9 9 24 17.7 36.4 26 10.2 6.8 20.1 14.4 31.2 19.5 7.9 3.6 16.5 5.6 25 7.7 12.9 3.3 45.1 7.7 39.2 7.7L3.4 424.6Z" />   
    
    <text class="textRed" x="200" y="350" font-size="72px" fill="white">Контакты</text>  
	  <text class="textBlack" x="850" y="350">тел.(650)5559462</text> 
</svg> 
</div>

Answer 7

Самое простое (и, наверное, разумное) - вставить статичную картинку фоном, но ей нельзя будет управлять, зато ее можно будет просто растягивать.

С использованием clip-path все сложнее и грязнее – его нельзя адекватно растянуть, сам "шейп" надо кидать в html (основопологающий элемент управления вектором отложили в самый дальний ящик, clip-path: path() сейчас working draft, и поддерживается только в firefox). Safari отнимает возможность импортить части svg, а с ней можно было-бы хранить все шейпы в отдельной свг по аналогии со стилями.

Вот моя чистенькая, как обычно рукописная реализация с svg/clip-path:

nav { 
  background: linear-gradient(to bottom, gray, black); 
  border-radius: 5px; 
  overflow: hidden; 
  font: 14px/20px Arial; 
  display: flex; 
} 
 
nav li { 
  list-style: none; 
  color: #FFF; 
  padding: 10px 10px 10px 70px; 
  background: linear-gradient(to bottom, red, darkred); 
  position: relative; 
} 
 
nav li.active ~ li { 
  background: transparent; 
} 
 
nav li.active:before { 
  content: ''; 
  display: block; 
  background: rgba(0,0,0,.4); 
  position: absolute; 
  right: -79px; /* артефакты на ретине */ 
  bottom: 0; 
  top: 0; 
  width: 80px; 
  background: linear-gradient(to bottom, red, darkred); 
  clip-path: url(#navDivider); 
}
<nav> 
  <li>Home</li> 
  <li class="active">About</li> 
  <li>Contacts</li> 
</nav> 
 
<svg> 
  <defs> 
    <clipPath id="navDivider" transform="scale(40)"> 
      <path d="M 0 0 C 1 0, 1 1, 2 1 S 1 1, 0 1"/> 
    </clipPath> 
  </defs> 
</svg>

READ ALSO
валидация формы, накопление ошибок

валидация формы, накопление ошибок

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

104
Cookies Laravel

Cookies Laravel

Есть domain1com и sub

88
Обработка нажатия telegram кнопки?

Обработка нажатия telegram кнопки?

Создал telegram бота, поставил Webhook, все работаетСейчас пытаюсь сделать кнопки, кнопки должны обратиться к серверу и с моего сервера выполнить...

82