Я пытаюсь воссоздать это изображение с помощью CSS:
Мне не нужно было бы это повторять. Это то, что я начал, но у него просто прямая линия:
#wave {
position: absolute;
height: 70px;
width: 600px;
background: #e0efe3;
}
<div id="wave"></div>
css
css-shapes
Stevenspiel
источник
источник
Ответы:
Не уверен, что это ваша форма, но она близка - вы можете поиграть со значениями:
https://jsfiddle.net/7fjSc/9/
#wave { position: relative; height: 70px; width: 600px; background: #e0efe3; } #wave:before { content: ""; display: block; position: absolute; border-radius: 100% 50%; width: 340px; height: 80px; background-color: white; right: -5px; top: 40px; } #wave:after { content: ""; display: block; position: absolute; border-radius: 100% 50%; width: 300px; height: 70px; background-color: #e0efe3; left: 0; top: 27px; }
<div id="wave"></div>
источник
Я считаю, что это правильный способ придать форму, которую вы хотите. Используя возможности SVG и контейнер, чтобы форма оставалась отзывчивой.
svg { display: inline-block; position: absolute; top: 0; left: 0; } .container { display: inline-block; position: relative; width: 100%; padding-bottom: 100%; vertical-align: middle; overflow: hidden; }
<div class="container"> <svg viewBox="0 0 500 500" preserveAspectRatio="xMinYMin meet"> <path d="M0,100 C150,200 350,0 500,100 L500,00 L0,0 Z" style="stroke: none; fill:red;"></path> </svg> </div>
источник
Моя реализация использует элемент svg в html, и я также сделал генератор для создания желаемой волны:
https://smooth.ie/blogs/news/svg-wavey-transitions-between-sections
<div style="height: 150px; overflow: hidden;"> <svg viewBox="0 0 500 150" preserveAspectRatio="none" style="height: 100%; width: 100%;"> <path d="M0.00,92.27 C216.83,192.92 304.30,8.39 500.00,109.03 L500.00,0.00 L0.00,0.00 Z" style="stroke: none;fill: #e1efe3;"></path> </svg> </div>
https://jsfiddle.net/1b8L7nax/5/
источник
Моя реализация на чистом CSS, основанная на выше, со 100% шириной. Надеюсь, поможет!
Показать фрагмент кода
#wave-container { width: 100%; height: 100px; overflow: hidden; } #wave { display: block; position: relative; height: 40px; background: black; } #wave:before { content: ""; display: block; position: absolute; border-radius: 100%; width: 100%; height: 300px; background-color: white; right: -25%; top: 20px } #wave:after { content: ""; display: block; position: absolute; border-radius: 100%; width: 100%; height: 300px; background-color: black; left: -25%; top: -240px; }
<div id="wave-container"> <div id="wave"> </div> </div>
источник
Мне нравится ответ ThomasA, но мне нужен более реалистичный контекст, когда волна используется для разделения двух div. Поэтому я создал более полную демонстрацию, в которой разделитель SVG идеально расположен между двумя div.
Теперь я подумал, что было бы круто пойти дальше. Что, если бы мы могли сделать все это в CSS без необходимости встроенного SVG ? Дело в том, чтобы избежать лишней разметки. Вот как я это сделал:
Два простых
<div>
:/** CSS using pseudo-elements: **/ #A { background: #0074D9; } #B { background: #7FDBFF; } #A::after { content: ""; position: relative; left: -3rem; /* padding * -1 */ top: calc( 3rem - 4rem / 2); /* padding - height/2 */ float: left; display: block; height: 4rem; width: 100vw; background: hsla(0, 0%, 100%, 0.5); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 70 500 60' preserveAspectRatio='none'%3E%3Crect x='0' y='0' width='500' height='500' style='stroke: none; fill: %237FDBFF;' /%3E%3Cpath d='M0,100 C150,200 350,0 500,100 L500,00 L0,0 Z' style='stroke: none; fill: %230074D9;'%3E%3C/path%3E%3C/svg%3E"); background-size: 100% 100%; } /** Cosmetics **/ * { margin: 0; } #A, #B { padding: 3rem; } div { font-family: monospace; font-size: 1.2rem; line-height: 1.2; } #A { color: white; }
<div id="A">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec quam tincidunt, iaculis mi non, hendrerit felis. Nulla pretium lectus et arcu tempus, quis luctus ex imperdiet. In facilisis nulla suscipit ornare finibus. … </div> <div id="B" class="wavy">… In iaculis fermentum lacus vel porttitor. Vestibulum congue elementum neque eget feugiat. Donec suscipit diam ligula, aliquam consequat tellus sagittis porttitor. Sed sodales leo nisl, ut consequat est ornare eleifend. Cras et semper mi, in porta nunc.</div>
Демо волнистый разделитель (с псевдоэлементами CSS, чтобы избежать лишней разметки)
Позиционировать было немного сложнее, чем со встроенным SVG, но он работает так же хорошо. (Можно использовать настраиваемые свойства CSS или переменные препроцессора, чтобы высота и отступы были легко читаемыми.)
Чтобы редактировать цвета, вам нужно отредактировать сам SVG с кодировкой URL.
Обратите внимание (как в первой демонстрации) на изменение,
viewBox
чтобы избавиться от ненужных пробелов в SVG. (Другой вариант - нарисовать другой SVG.)Еще одна вещь, на которую следует обратить внимание, - это
background-size
набор,100% 100%
чтобы заставить ее растягиваться в обоих направлениях.источник
Недавно был представлен замечательный инструмент Get Waves, в котором вы можете просто из пользовательского интерфейса создать свои собственные волны, а затем экспортировать их в формат SVG. Это так же просто, как зайти на сайт https://getwaves.io/ и насладиться им!
Редактировать:
Недавно я обнаружил также новый инструмент - https://shapedivider.app/
источник
Вот еще один способ сделать это :) Идея состоит в том, чтобы создать полигон траектории с волной на одной стороне.
Этот подход достаточно гибкий. Вы можете изменить положение (слева, справа, сверху или снизу), в котором появляется волна, изменить волновую функцию на любую функцию (t), которая отображается на [0,1]). Многоугольник также можно использовать для формы снаружи, что позволяет тексту обтекать волну в «левой» или «правой» ориентации.
В конце можно раскомментировать пример, демонстрирующий анимацию волны.
function PolyCalc(f /*a function(t) from [0, infinity) => [0, 1]*/, s, /*a slice function(y, i) from y [0,1] => [0, 1], with slice index, i, in [0, n]*/ w /*window size in seconds*/, n /*sample size*/, o /*orientation => left/right/top/bottom - the 'flat edge' of the polygon*/ ) { this.polyStart = "polygon("; this.polyLeft = this.polyStart + "0% 0%, "; //starts in the top left corner this.polyRight = this.polyStart + "100% 0%, "; //starts in the top right corner this.polyTop = this.polyStart + "0% 0%, "; // starts in the top left corner this.polyBottom = this.polyStart + "0% 100%, ";//starts in the bottom left corner var self = this; self.mapFunc = s; this.func = f; this.window = w; this.count = n; var dt = w/n; switch(o) { case "top": this.poly = this.polyTop; break; case "bottom": this.poly = this.polyBottom; break; case "right": this.poly = this.polyRight; break; case "left": default: this.poly = this.polyLeft; break; } this.CalcPolygon = function(t) { var p = this.poly; for (i = 0; i < this.count; i++) { x = 100 * i/(this.count-1.0); y = this.func(t + i*dt); if (typeof self.mapFunc !== 'undefined') y=self.mapFunc(y, i); y*=100; switch(o) { case "top": p += x + "% " + y + "%, "; break; case "bottom": p += x + "% " + (100-y) + "%, "; break; case "right": p += (100-y) + "% " + x + "%, "; break; case "left": default: p += y + "% " + x + "%, "; break; } } switch(o) { case "top": p += "100% 0%)"; break; case "bottom": p += "100% 100%)"; break; case "right": p += "100% 100%)"; break; case "left": default: p += "0% 100%)"; break; } return p; } }; var text = document.querySelector("#text"); var divs = document.querySelectorAll(".wave"); var freq=2*Math.PI; //angular frequency in radians/sec var windowWidth = 1; //the time domain window which determines the range from [t, t+windowWidth] that will be evaluated to create the polygon var sampleSize = 60; divs.forEach(function(wave) { var loc = wave.classList[1]; var polyCalc = new PolyCalc( function(t) { //The time domain wave function return (Math.sin(freq * t) + 1)/2; //sine is [-1, -1], so we remap to [0,1] }, function(y, i) { //slice function, takes the time domain result and the slice index and returns a new value in [0, 1] return MapRange(y, 0.0, 1.0, 0.65, 1.0); //Here we adjust the range of the wave to 'flatten' it out a bit. We don't use the index in this case, since it is irrelevant }, windowWidth, //1 second, which with an angular frequency of 2pi rads/sec will produce one full period. sampleSize, //the number of samples to make, the larger the number, the smoother the curve, but the more pionts in the final polygon loc //the location ); var polyText = polyCalc.CalcPolygon(0); wave.style.clipPath = polyText; wave.style.shapeOutside = polyText; wave.addEventListener("click",function(e) {document.querySelector("#polygon").innerText = polyText;}); }); function MapRange(value, min, max, newMin, newMax) { return value * (newMax - newMin)/(max-min) + newMin; } //Animation - animate the wave by uncommenting this section //Also demonstrates a slice function which uses the index of the slice to alter the output for a dampening effect. /* var t = 0; var speed = 1/180; var polyTop = document.querySelector(".top"); var polyTopCalc = new PolyCalc( function(t) { return (Math.sin(freq * t) + 1)/2; }, function(y, i) { return MapRange(y, 0.0, 1.0, (sampleSize-i)/sampleSize, 1.0); }, windowWidth, sampleSize, "top" ); function animate() { var polyT = polyTopCalc.CalcPolygon(t); t+= speed; polyTop.style.clipPath = polyT; requestAnimationFrame(animate); } requestAnimationFrame(animate); */
div div { padding:10px; /*overflow:scroll;*/ } .left { height:100%; width:35%; float:left; } .right { height:200px; width:35%; float:right; } .top { width:100%; height: 200px; } .bottom { width:100%; height:200px; } .green { background:linear-gradient(to bottom, #b4ddb4 0%,#83c783 17%,#52b152 33%,#008a00 67%,#005700 83%,#002400 100%); } .mainContainer { width:100%; float:left; } #polygon { padding-left:20px; margin-left:20px; width:100%; }
<div class="mainContainer"> <div class="wave top green"> Click to see the polygon CSS </div> <!--div class="wave left green"> </div--> <!--div class="wave right green"> </div--> <!--div class="wave bottom green"></div--> </div> <div id="polygon"></div>
источник