SVG แบบอินไลน์ใน CSS


284

เป็นไปได้หรือไม่ที่จะใช้คำนิยาม SVG แบบอินไลน์ใน CSS?

ฉันหมายถึงสิ่งที่ชอบ:

.my-class {
  background-image: <svg>...</svg>;
}

1
คุณพยายามทำอะไรเพิ่มรูปภาพ "แหล่งที่มา" ลงในสไตล์ชีท
Zuul

1
ระวังว่าโซลูชันที่เสนอจะไม่ทำงานกับภาพ CSS, <img>แท็กHTML และกรณีอื่น ๆ หาก SVG เป็นการผสมผสานกันของภาพหลายภาพ (ยกเว้นกรณีที่ฝังไว้) ดูภาพพื้นหลัง SVG พร้อมหน้ากากที่ใช้ภาพภายนอกไม่ทำงานและข้อ จำกัดเฉพาะเกี่ยวกับ SVG ภาพ
Skippy le Grand Gourou

คำตอบ:


376

ใช่มันเป็นไปได้ ลองสิ่งนี้:

body { background-image: 
        url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='%23F00'/><stop offset='90%' stop-color='%23fcc'/> </linearGradient><rect fill='url(%23gradient)' x='0' y='0' width='100%' height='100%'/></svg>");
      }

(โปรดทราบว่าเนื้อหา SVG จะต้องมีการหลีกเลี่ยง URL เพื่อให้สามารถใช้งาน#ได้เช่นถูกแทนที่ด้วย%23)

งานนี้ใน IE 9 (ซึ่งสนับสนุน SVG) Data-URLs ทำงานได้กับ IE เวอร์ชั่นเก่า (เช่นมีข้อ จำกัด ) แต่ก็ไม่รองรับ SVG


8
เบราว์เซอร์เดียวที่ทำงานได้ดีคือ Safari (5.1.4) ใน Opera 11.62 การไล่ระดับสีดำใน IE 9 และ Firefox 12 เป็นสีขาว ใน Chrome 19 จะใช้งานได้เว้นแต่คุณจะระบุความกว้าง / ความสูงของ SVG ในหน่วย% ฉันว่ามันแปลกกว่าคุณสมบัติจริง มันเป็นการค้นพบที่ยอดเยี่ยม
toniedzwiedz

4
ใช่แล้ว ... ฉันยังอยากเห็นหน้าตาของเพื่อนร่วมงานเมื่อฉันแสดงสัตว์ประหลาดตัวน้อยน่ารักแบบนี้ดังนั้นขอบคุณอีกครั้งสำหรับการแสดงว่าเป็นไปได้ ฉันเพิ่งไปสเปคมาตรฐานและระบุว่ามันเป็นไปไม่ได้จริงซึ่งกลายเป็นข้อผิดพลาด (เรียงลำดับ)
toniedzwiedz

18
"ความเข้ากันไม่ได้ของเบราว์เซอร์" ที่นี่ส่วนใหญ่เป็นเพียงการขาดการหลบหนี URL ที่เหมาะสมทุกอย่างภายในurl()ควรจะหนี URL ดูjsfiddle.net/6WAtQสำหรับตัวอย่างที่ใช้งานได้ดีใน Opera, Firefox และ Safari
Erik Dahlström

3
มีความแตกต่างใด ๆ ที่เข้ากันได้ระหว่าง base64 เข้ารหัส svg กับไม่ใช่ base64? Base64 bloats ไฟล์ css ของฉันฉันกำลังคิดใช้ inline svgs ..
enapupe

4
หมายเหตุวิธีมาตรฐานในการระบุชุดอักขระคือ "; charset = UTF-8" แทน "; utf8" tools.ietf.org/html/rfc2397
Keith Shaw

240

สายไปหน่อย แต่ถ้าคุณคนใดบ้าคลั่งที่พยายามใช้inline SVG เป็นพื้นหลังคำแนะนำในการหลบหนีด้านบนจะไม่ทำงาน สำหรับวิธีนี้ใช้ไม่ได้ใน IE และขึ้นอยู่กับเนื้อหาของ SVG ของคุณเทคนิคจะทำให้เกิดปัญหาในเบราว์เซอร์อื่นเช่น FF

หากคุณ base64 เข้ารหัส svg (ไม่ใช่ url ทั้งหมดเพียงแค่แท็ก svg และเนื้อหาของมัน!) มันทำงานได้ในทุกเบราว์เซอร์ นี่คือตัวอย่าง jsfiddle เดียวกันใน base64: http://jsfiddle.net/vPA9z/3/

CSS ตอนนี้มีลักษณะดังนี้:

body { background-image: 
    url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PGxpbmVhckdyYWRpZW50IGlkPSdncmFkaWVudCc+PHN0b3Agb2Zmc2V0PScxMCUnIHN0b3AtY29sb3I9JyNGMDAnLz48c3RvcCBvZmZzZXQ9JzkwJScgc3RvcC1jb2xvcj0nI2ZjYycvPiA8L2xpbmVhckdyYWRpZW50PjxyZWN0IGZpbGw9J3VybCgjZ3JhZGllbnQpJyB4PScwJyB5PScwJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJy8+PC9zdmc+");

อย่าลืมลบ URL ใด ๆ ที่หนีออกไปก่อนที่จะแปลงเป็น base64 ในคำอื่น ๆ ตัวอย่างด้านบนแสดง color = '# fcc' ที่แปลงเป็น color = '% 23fcc' คุณควรกลับไปที่ #

เหตุผลที่ทำให้ base64 ทำงานได้ดีขึ้นคือมันกำจัดปัญหาทั้งหมดด้วยการเสนอราคาเดี่ยวและสองครั้งและการหลบหนี URL

หากคุณกำลังใช้ JS คุณสามารถใช้window.btoa()เพื่อสร้าง base64 svg ของคุณ และถ้ามันไม่ทำงาน (มันอาจจะบ่นเกี่ยวกับตัวอักษรที่ไม่ถูกต้องในสตริง) คุณก็สามารถใช้https://www.base64encode.org/

ตัวอย่างการตั้งค่าพื้นหลัง div:

var mySVG = "<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='#F00'/><stop offset='90%' stop-color='#fcc'/> </linearGradient><rect fill='url(#gradient)' x='0' y='0' width='100%' height='100%'/></svg>";
var mySVG64 = window.btoa(mySVG);
document.getElementById('myDiv').style.backgroundImage = "url('data:image/svg+xml;base64," + mySVG64 + "')";
html, body, #myDiv {
  width: 100%;
  height: 100%;
  margin: 0;
}
<div id="myDiv"></div>

ด้วย JS คุณสามารถสร้าง SVG ได้ทันทีแม้กระทั่งการเปลี่ยนพารามิเตอร์

หนึ่งในบทความที่ดีกว่าเกี่ยวกับการใช้ SVG อยู่ที่นี่: http://dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/

หวังว่านี่จะช่วยได้

ไมค์


2
ขอบคุณชาย วิธีแก้ปัญหาของ Base64 ทำงานได้ยอดเยี่ยมในขณะที่ฉันมีปัญหากับคำตอบที่ยอมรับได้
Marcel

1
คุณช่วยชีวิตฉัน. ฉันมีภาพเส้นขอบ SVG ที่ทำงานบนโครเมียม แต่ไม่ได้อยู่บน FF ตอนนี้มันใช้งานได้! : D
Papipo

ช่วยฉันด้วย (หลังจากหมดเวลาลองคำตอบที่ยอมรับ) - นี่ควรเป็นคำตอบที่ยอมรับได้แน่นอน
Katai

หากสิ่งนี้ยังคงไม่ทำงานสำหรับคุณ - ตรวจสอบให้แน่ใจว่าคุณได้xmlnsตั้งค่าแอตทริบิวต์เป็นsvgองค์ประกอบก่อนที่คุณจะเข้ารหัส base64 เช่น<svg xmlns="http://www.w3.org/2000/svg">...</svg>เบราว์เซอร์บางครั้งจะทำไม่ได้เมื่อ svg อยู่ใน HTML โดยตรง - นี่ไม่ใช่กรณี :)
jave.web

ในกรณีที่ใครบางคนยังคงดูคำตอบนี้ 6 ปีต่อมา: คุณอาจไม่ควร base64 SVGs css-tricks.com/probably-dont-base64-svg
Volker E.

38

สำหรับคนที่ยังคงดิ้นรนฉันพยายามทำให้เบราว์เซอร์สมัยใหม่ทั้งหมด IE11 ขึ้นไปทำงานได้

base64 ไม่มีตัวเลือกสำหรับฉันเพราะฉันต้องการใช้ SASS เพื่อสร้างไอคอน SVG ตามสีที่กำหนด ตัวอย่างเช่น: @include svg_icon(heart, #FF0000);ด้วยวิธีนี้ฉันสามารถสร้างไอคอนบางสีได้และต้องฝังรูปร่าง SVG หนึ่งครั้งใน CSS (ด้วย base64 คุณต้องฝัง SVG ในทุก ๆ สีที่คุณต้องการใช้)

มีสามสิ่งที่คุณต้องระวัง:

  1. URL เข้ารหัส SVG ของคุณ ตามที่คนอื่นแนะนำคุณต้อง URL เข้ารหัสสตริง SVG ทั้งหมดของคุณเพื่อให้ทำงานใน IE11 ในกรณีของฉันฉันทิ้งค่าสีในฟิลด์เช่นfill="#00FF00"และstroke="#FF0000"และแทนที่ด้วยตัวแปร SASS fill="#{$color-rgb}"เพื่อให้สามารถแทนที่เหล่านี้ด้วยสีที่ฉันต้องการ คุณสามารถใช้ตัวแปลงออนไลน์ใด ๆเพื่อเข้ารหัส URL ที่เหลือของสตริง คุณจะได้สตริง SVG ดังนี้:

    % 3Csvg% 20xmlns% 3D% 27http% 3A% 2F% 2Fwww.w3.org% 2F2000% 2Fsvg% 27% 20viewBox% 3D% 270% 200% 20494.572% 20494.572% 27% 20width% 3D% 27512% 27% 20height% 3D % 27512% 27% 3E% 0A% 20% 20% 3Cpath% 20d% 3D% 27M257.063% 200C127.136% 200% 2021.808% 20,105.33% 2021.808% 20235.266c0% 2,041.012 2,010.535%%% 2,079.541 2,028.973% 20113.104L3.825 % 20464.586c345% 2012.797% 2041.813% 2012.797% 2015.467% 200% 2029.872-4.721% 2041.813-12.797v158.184z% 27% 20fill% 3D% 27 # {$ color-rgb} % 27% 2F% 3E% 3C 3E


  1. ละเว้น UTF8 CHARSET ใน DATA URLเมื่อสร้าง URL ข้อมูลของคุณคุณต้องปล่อยให้ charset ทำงานใน IE11

    ไม่ใช่ภาพพื้นหลัง: url (ข้อมูล: image / svg + xml; utf-8,% 3Csvg% 2 .... )
    แต่ภาพพื้นหลัง: url (ข้อมูล: ภาพ / svg + xml,% 3Csvg% 2 ... .)


  1. ใช้ RGB () สีแทน HEX Firefox ไม่เหมือน # ในรหัส SVG ดังนั้นคุณต้องแทนที่ค่า hex สีของคุณด้วยค่า RGB

    ไม่เติม = "# FF0000"
    แต่เติม = "rgb (255,0,0)"

ในกรณีของฉันฉันใช้ SASS เพื่อแปลงเลขฐานสิบหกที่กำหนดให้เป็นค่า rgb ที่ถูกต้อง ตามที่ระบุไว้ในความคิดเห็นที่ดีที่สุดคือ URL เข้ารหัสสตริง RGB ของคุณเช่นกัน (ดังนั้นคอมม่ากลายเป็น% 2C)

@mixin svg_icon($id, $color) {
   $color-rgb: "rgb(" + red($color) + "%2C" + green($color) + "%2C" + blue($color) + ")";
   @if $id == heart {
      background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20494.572%20494.572%27%20width%3D%27512%27%20height%3D%27512%27%3E%0A%20%20%3Cpath%20d%3D%27M257.063%200C127.136%200%2021.808%20105.33%2021.808%20235.266c0%204%27%20fill%3D%27#{$color-rgb}%27%2F%3E%3C%2Fsvg%3E');
   }
}

ฉันรู้ว่านี่อาจไม่ใช่ทางออกที่ดีที่สุดสำหรับ SVG ที่ซับซ้อนมาก (อินไลน์ SVG ไม่เคยเป็นเช่นนั้น) แต่สำหรับไอคอนแบบแบนที่มีสีเพียงสองสามอันมันใช้งานได้ดีมาก

ฉันสามารถออกบิตแมปสไปรต์ทั้งหมดและแทนที่ด้วย inline SVG ใน CSS ของฉันซึ่งกลายเป็นเพียงประมาณ 25kb หลังจากการบีบอัด ดังนั้นจึงเป็นวิธีที่ยอดเยี่ยมในการ จำกัด จำนวนคำขอที่ไซต์ของคุณต้องทำโดยไม่ทำให้ไฟล์ CSS ของคุณพองตัว


1
Btw, แก้ไขฉันถ้าฉันผิด แต่rgb(255,0,0)ควรจะrgb(255%2C0%2C0)เข้ารหัสครั้งเดียว
แคปซูล

1
ฉันหมายความว่าฉันไม่ได้เข้ารหัสสตริง RGB แต่ก็ยังใช้งานได้ แต่การเข้ารหัสมันตามที่คุณกล่าวถึงน่าจะดีกว่า
Davy Baert

1
ที่จริงแล้วฉันเพิ่งทดสอบและใช้%23ff0000งานได้ดี#ff0000ใน Firefox
แคปซูล

1
@Capsule ฉันไม่รู้ว่าเกิดอะไรขึ้น แต่% 23ff0000 เป็นวิธีเดียวที่ใช้ได้สำหรับฉันทั้ง Chrome และ FF # ff0000 ไม่ทำงานและไม่ใช้วิธีการ RGB (255,0,0) และ rgb (255% 2C0% 2C0)
Ideogram

1
วิธีการ (รวมถึงรหัส SCSS) ที่ต้องใช้การเข้ารหัสน้อยกว่า: codepen.io/jakob-e/pen/doMoML
Sphinxxx

26

บน Mac / Linux คุณสามารถแปลงไฟล์ SVG เป็นค่าที่เข้ารหัสพื้นฐาน 64 สำหรับแอตทริบิวต์พื้นหลัง CSS ด้วยคำสั่ง bash นี้:

echo "background: transparent url('data:image/svg+xml;base64,"$(openssl base64 < path/to/file.svg)"') no-repeat center center;"

ทดสอบบน Mac OS X ด้วยวิธีนี้คุณจะหลีกเลี่ยงความยุ่งเหยิงของ URL

โปรดจำไว้ว่า base64 เข้ารหัสไฟล์ SVG เพิ่มขนาดให้ดูcss-tricks.com บล็อกโพสต์


2
ถึงผู้อ่าน: โปรดแสดงความคิดเห็นความคิดเห็นของคุณแทนที่จะเพียงแค่ลงคะแนนดังนั้นคำตอบนี้จะได้รับการปรับปรุงให้ดียิ่งขึ้นด้วยความร่วมมือของคุณ การทำงานร่วมกันเป็นสิ่งจำเป็นในเว็บไซต์ถามตอบเช่นนี้ ขอบคุณ!
araks

2
@LorDex ลิงค์ที่คุณให้ไว้ในความคิดเห็นของคุณก็เช่นเดียวกันที่ในคำตอบของฉัน :)
Araks

10

ฉันได้ทำการสาธิต CodePen ที่มีปัญหาเดียวกันกับการฝัง SVG แบบอินไลน์ลงใน CSS โซลูชันที่ทำงานกับ SCSS คือการสร้างฟังก์ชั่นการเข้ารหัส URL อย่างง่าย

ฟังก์ชั่นการเปลี่ยนสตริงสามารถสร้างได้จากฟังก์ชั่น str-slice, str-index ในตัว (ดูcss-tricks , ขอบคุณ Hugo Giraudel)

จากนั้นเพียงแค่เปลี่ยน%, <, >, ", ', กับ%xxรหัส:

@function svg-inline($string){
  $result: str-replace($string, "<svg", "<svg xmlns='http://www.w3.org/2000/svg'");
  $result: str-replace($result, '%', '%25');
  $result: str-replace($result, '"', '%22');
  $result: str-replace($result, "'", '%27');
  $result: str-replace($result, ' ', '%20');
  $result: str-replace($result, '<', '%3C');
  $result: str-replace($result, '>', '%3E');
  @return "data:image/svg+xml;utf8," + $result;
}

$mySVG: svg-inline("<svg>...</svg>");

html {
  height: 100vh;
  background: url($mySVG) 50% no-repeat;
}

นอกจากนี้ยังมีimage-inlineฟังก์ชั่นตัวช่วยในเข็มทิศ แต่เนื่องจากไม่รองรับใน CodePen โซลูชันนี้จึงอาจมีประโยชน์

การสาธิตเกี่ยวกับ CodePen: http://codepen.io/terabaud/details/PZdaJo/


1
ฉันยังสร้างปากกาที่ให้คุณแปลงสตริง svg เป็นค่า css ที่เหมาะสม: s.codepen.io/LukyVj/debug/693cbcc30258bf67b8c30047cce060eb ดังนั้นโดยทั่วไปคุณวางของคุณ<svg><path></svg>ลงใน textarea ด้านบนโดยตรง ภายในurl()ค่า
LukyVj

1
มันใช้งานได้ดีมาก ขอบคุณ. หนึ่งบันทึก คุณต้องใช้; charset = utf8 เพื่อให้มันใช้งานได้ใน IE
Daniel Lefebvre

4

SVG แบบอินไลน์มาจากแหล่งบุคคลที่สาม (เช่นชาร์ตของ Google) อาจไม่มีแอตทริบิวต์ XML namespace ( xmlns="http://www.w3.org/2000/svg") ในองค์ประกอบ SVG (หรืออาจถูกลบออกเมื่อมีการแสดงผล SVG แล้ว - ไม่ใช่ทั้งผู้ตรวจสอบเบราว์เซอร์หรือคำสั่ง jQuery จากคอนโซลเบราว์เซอร์

เมื่อคุณต้องการ re-purpose svg snippets เหล่านี้สำหรับความต้องการอื่น ๆ ของคุณ (ภาพพื้นหลังใน CSS หรือองค์ประกอบ img ใน HTML) ระวัง namespace ที่หายไป หากไม่มีเบราว์เซอร์เนมสเปซอาจปฏิเสธที่จะแสดง SVG (โดยไม่คำนึงถึงการเข้ารหัส utf8 หรือ base64)


4

ฉันพบวิธีแก้ปัญหาหนึ่งสำหรับ SVG แต่มันก็ใช้ได้กับ Webkit เท่านั้นฉันแค่ต้องการแชร์วิธีแก้ปัญหากับคุณ ในตัวอย่างของฉันแสดงวิธีใช้องค์ประกอบ SVG จาก DOM เป็นพื้นหลังผ่านตัวกรอง (background-image: url ('# glyph') ไม่ทำงาน)

คุณลักษณะที่จำเป็นสำหรับการแสดงผลไอคอน SVG นี้:

  1. การใช้เอฟเฟ็กต์ตัวกรอง SVG กับองค์ประกอบ HTML โดยใช้ CSS (IE และ Edge ไม่รองรับ)
  2. feImage รองรับการโหลดชิ้นส่วน (Firefox ไม่รองรับ)

.test {
  /*  background-image: url('#glyph');
    background-size:100% 100%;*/
    filter: url(#image); 
    height:100px;
    width:100px;
}
.test:before {
   display:block;
   content:'';
   color:transparent;
}
.test2{
  width:100px;
  height:100px;
}
.test2:before {
   display:block;
   content:'';
   color:transparent;
   filter: url(#image); 
   height:100px;
   width:100px;
}
<svg style="height:0;width:0;" version="1.1" viewbox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
     <g id="glyph">
          <path id="heart" d="M100 34.976c0 8.434-3.635 16.019-9.423 21.274h0.048l-31.25 31.25c-3.125 3.125-6.25 6.25-9.375 6.25s-6.25-3.125-9.375-6.25l-31.202-31.25c-5.788-5.255-9.423-12.84-9.423-21.274 0-15.865 12.861-28.726 28.726-28.726 8.434 0 16.019 3.635 21.274 9.423 5.255-5.788 12.84-9.423 21.274-9.423 15.865 0 28.726 12.861 28.726 28.726z" fill="crimson"/>
     </g>
    <svg id="resized-glyph"  x="0%" y="0%" width="24" height="24" viewBox="0 0 100 100" class="icon shape-codepen">
      <use xlink:href="#glyph"></use>
    </svg>
     <filter id="image">
       <feImage xlink:href="#resized-glyph" x="0%" y="0%" width="100%" height="100%" result="res"/>
       <feComposite operator="over" in="res" in2="SourceGraphic"/>
    </filter>
 </defs>
</svg>
<div class="test">
</div>
<div class="test2">
</div>

อีกวิธีหนึ่งคือใช้การเข้ารหัส URL

var container = document.querySelector(".container");
var svg = document.querySelector("svg");
var svgText = (new XMLSerializer()).serializeToString(svg);
container.style.backgroundImage = `url(data:image/svg+xml;utf8,${encodeURIComponent(svgText)})`;
.container{
  height:50px;
  width:250px;
  display:block;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: contain;
}
<svg  height="100" width="500" xmlns="http://www.w3.org/2000/svg">
    <ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" />
</svg>
<div class="container"></div>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.