Hình dạng gợn sóng với css


80

Tôi đang cố gắng tạo lại hình ảnh này bằng CSS:

hình dạng con đường

Tôi sẽ không cần nó lặp lại. Đây là những gì tôi đã bắt đầu nhưng nó chỉ có một đường thẳng:

#wave {
  position: absolute;
  height: 70px;
  width: 600px;
  background: #e0efe3;
}
<div id="wave"></div>


2
nếu u muốn tái tạo này với css chỉ cho kích thước sử dụng SVG thay
iKamy

Bạn có suy nghĩ gì không? Bất cứ điều gì mà bạn đã thử?
David Fritsch

1
Tại sao không chỉ sử dụng một hình nền? Đôi khi, tốt nhất là bạn không nên lạm dụng hoặc "tận dụng" sức mạnh của CSS khi một hình ảnh .png đơn giản có thể khiến bạn tốn 20 byte.
ProfileTwist

1
Đối với hình dạng cong kép, bạn có thể kiểm tra câu hỏi này: Hình dạng cong kép
web-tiki

Tôi tìm thấy cái này bootsnipp.com/snippets/yN3Zo
core114

Câu trả lời:


81

Tôi không chắc đó là hình dạng của bạn nhưng nó gần giống - bạn có thể chơi với các giá trị:

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>


1
Điều này rơi ra mà không có chiều rộng được thiết lập. Tôi luôn cần chiều rộng = 100%. Làm tốt lắm.
MH

4
Có một khoảng trống khó coi khi cả hai yếu tố giả gặp nhau.
Fabien Snauwaert

89

Tôi nghĩ đây là cách phù hợp để tạo hình như ý muốn. Bằng cách sử dụng các khả năng SVG và một hộp chứa để giữ cho hình dạng đáp ứng.

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>


1
Mặc dù bạn có thể vẽ và tạo hình ảnh động bằng SVG nhưng hầu hết mọi người đều xuất tệp SVG của họ từ phần mềm dựa trên Vector như Corel hoặc Illustrator và Chèn vào tệp HTML, sau đó bạn có thể tạo kiểu nhiều hơn với CSS hoặc thậm chí thao tác các nút với JS hoặc SVG Các thư viện. và Thats Case cho SVG vì Nó có nghĩa vụ phải giải quyết những khó khăn với bản vẽ trong CSS
iKamy

Tôi đã xây dựng điều này trong câu trả lời của mình bằng cách thêm hai div để làm cho ví dụ thực tế hơn, cắt SVG để loại bỏ các lề không mong muốn và loại bỏ SVG nội tuyến có lợi cho giải pháp CSS.
Fabien Snauwaert

43

Việc triển khai của tôi sử dụng phần tử svg trong html và tôi cũng đã tạo một trình tạo để tạo wave mà bạn muốn:

https://smooth.ie/blogs/news/svg-wavey-transitions-between-section

<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/



8
Chưa bao giờ xảy ra trước đây nhưng tôi thực sự đăng nhập chỉ để ủng hộ câu trả lời này cho trình tạo sóng. Tôi ghét SVG và bạn đã tiết kiệm cho tôi rất nhiều thời gian!
GoreDefex

21

Triển khai CSS thuần túy của tôi dựa trên với chiều rộng 100%. Hy vọng nó giúp!


1
Nếu không kiểm tra mã quá sâu, điều này có vẻ tốt hơn so với câu trả lời được chấp nhận hiện tại, đối với tôi (Firefox 61.0a1) hiển thị một vài pixel nằm ngang thẳng ở giữa.
user4642212

Thay đổi màu sắc và bạn sẽ thấy :)
PVermeer

18

Gần đây, một công cụ tuyệt vời có tên là Get Waves đã được giới thiệu, nơi bạn có thể chỉ cần từ UI tạo wave của riêng mình và sau đó xuất nó sang định dạng SVG. Điều này đơn giản như truy cập trang web https://getwaves.io/ và tận hưởng nó!

Biên tập:

Gần đây, tôi cũng đã khám phá ra một công cụ mới - https://shapedivider.app/


1
Điều này đã tiết kiệm cho tôi rất nhiều rắc rối. Cảm ơn bạn!
Liz

Rất vui được giúp đỡ :)
Daniel Danielecki

17

Tôi thích câu trả lời của ThomasA, nhưng muốn có bối cảnh thực tế hơn với làn sóng được sử dụng để phân tách hai div. Vì vậy, tôi đã tạo một bản trình diễn hoàn chỉnh hơn trong đó dấu phân tách SVG được định vị hoàn hảo giữa hai div.

css dải phân cách gợn sóng trong CSS

Bây giờ tôi nghĩ sẽ rất tuyệt nếu tiến xa hơn. Điều gì sẽ xảy ra nếu chúng ta có thể làm tất cả điều này trong CSS mà không cần SVG nội tuyến ? Vấn đề là để tránh đánh dấu thêm. Đây là cách tôi đã làm điều đó:

Hai đơn giản <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>

Demo Dải phân cách lượn sóng (với các phần tử giả CSS để tránh đánh dấu thêm)

Việc định vị phức tạp hơn một chút so với SVG nội tuyến nhưng hoạt động tốt. (Có thể sử dụng thuộc tính tùy chỉnh CSS hoặc các biến tiền xử lý để giữ cho chiều cao và phần đệm dễ đọc.)

Để chỉnh sửa màu sắc, bạn cần phải chỉnh sửa chính SVG được mã hóa URL.

Hãy chú ý (như trong bản demo đầu tiên) đến một thay đổi trong cáchviewBox loại bỏ các khoảng trống không mong muốn trong SVG. (Một tùy chọn khác là vẽ một SVG khác.)

Một điều cần chú ý ở đây là background-sizethiết lập để 100% 100%làm cho nó kéo dài theo cả hai hướng.


3

Đây là một cách khác để làm điều đó :) Khái niệm là tạo một đa giác đường dẫn clip với sóng là một bên.

Cách tiếp cận này khá linh hoạt. Bạn có thể thay đổi vị trí (trái, phải, trên hoặc dưới) nơi sóng xuất hiện, thay đổi hàm sóng thành bất kỳ hàm nào (t) ánh xạ thành [0,1]). Đa giác cũng có thể được sử dụng cho hình dạng bên ngoài, cho phép văn bản chảy xung quanh làn sóng khi ở hướng 'trái' hoặc 'phải'.

Ở phần cuối, một ví dụ bạn có thể bỏ ghi chú thể hiện hoạt ảnh của wave.

 

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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.