n. e•mog•ri•fi•er [ē-'mä-grƏ-,fī-Ər] - ยูทิลิตี้สำหรับการเปลี่ยนแปลงลักษณะหรือรูปลักษณ์ของอีเมล HTML โดยสมบูรณ์ โดยเฉพาะ ในลักษณะที่น่าอัศจรรย์หรือแปลกประหลาดเป็นพิเศษ
Emogrifier แปลงสไตล์ CSS เป็นแอตทริบิวต์สไตล์อินไลน์ในโค้ด HTML ของคุณ เพื่อให้แน่ใจว่าจะแสดงบนอีเมลและอุปกรณ์มือถือที่เหมาะสมซึ่งขาดการสนับสนุนสไตล์ชีท
ยูทิลิตี้นี้ได้รับการพัฒนาโดยเป็นส่วนหนึ่งของ Intervals เพื่อจัดการกับปัญหาที่เกิดจากไคลเอนต์อีเมลบางตัว (เช่น Outlook 2007 และ GoogleMail) เมื่อพูดถึงวิธีจัดการกับสไตล์ที่มีอยู่ในอีเมล HTML ดังที่นักพัฒนาและนักออกแบบเว็บไซต์หลายคนทราบดีอยู่แล้วว่าไคลเอนต์อีเมลบางรายขึ้นชื่อในเรื่องการขาดการสนับสนุน CSS แม้ว่าจะมีการพยายามพัฒนามาตรฐานอีเมลทั่วไป แต่การนำไปปฏิบัติก็ยังเป็นหนทางที่ปิดอยู่
ปัญหาหลักของโปรแกรมรับส่งเมลที่ไม่ให้ความร่วมมือคือส่วนใหญ่มักจะคำนึงถึง CSS แบบอินไลน์เท่านั้น โดยละทิ้งองค์ประกอบ <style>
ทั้งหมด และลิงก์ไปยังสไตล์ชีทในองค์ประกอบ <link>
Emogrifier แก้ปัญหานี้โดยการแปลงสไตล์ CSS เป็นแอตทริบิวต์สไตล์อินไลน์ในโค้ด HTML ของคุณ
Emogrifier แปลง HTML ของคุณโดยอัตโนมัติโดยแยกวิเคราะห์ CSS และแทรกคำจำกัดความ CSS ของคุณลงในแท็กภายใน HTML ตามตัวเลือก CSS ของคุณ
สำหรับการติดตั้ง emogrifier ให้เพิ่ม pelago/emogrifier
ในส่วน require
ใน composer.json
ของโปรเจ็กต์ของคุณ หรือคุณสามารถใช้ composer ดังต่อไปนี้:
composer require pelago/emogrifier
ดู https://getcomposer.org/ สำหรับข้อมูลและเอกสารเพิ่มเติม
วิธีพื้นฐานที่สุดในการใช้คลาส CssInliner
คือการสร้างอินสแตนซ์ด้วย HTML ดั้งเดิม ใส่ CSS ภายนอกในบรรทัด จากนั้นจึงนำ HTML ที่ได้กลับมา:
use Pelago Emogrifier CssInliner ;
…
$ visualHtml = CssInliner:: fromHtml ( $ html )-> inlineCss ( $ css )-> render ();
หากไม่มีไฟล์ CSS ภายนอกและ CSS ทั้งหมดอยู่ภายในองค์ประกอบ <style>
ใน HTML คุณสามารถละเว้นพารามิเตอร์ $css
ได้:
$ visualHtml = CssInliner:: fromHtml ( $ html )-> inlineCss ()-> render ();
หากคุณต้องการกลับเฉพาะเนื้อหาขององค์ประกอบ <body>
แทนที่จะเป็นเอกสาร HTML ที่สมบูรณ์ คุณสามารถใช้เมธอด renderBodyContent
แทนได้:
$ bodyContent = $ visualHtml = CssInliner:: fromHtml ( $ html )-> inlineCss ()
-> renderBodyContent ();
หากคุณต้องการแก้ไขกระบวนการอินไลน์ด้วยตัวเลือกใดๆ ที่มี คุณจะต้องเรียกวิธีการที่เกี่ยวข้องก่อนที่จะอินไลน์ CSS รหัสจะมีลักษณะดังนี้:
$ visualHtml = CssInliner:: fromHtml ( $ html )-> disableStyleBlocksParsing ()
-> inlineCss ( $ css )-> render ();
นอกจากนี้ยังมีคลาสการประมวลผล HTML อื่นๆ ที่มีอยู่ (ทั้งหมดเป็นคลาสย่อยของ AbstractHtmlProcessor
) ซึ่งคุณสามารถใช้เพื่อเปลี่ยนแปลง HTML เพิ่มเติมได้หลังจากอินไลน์ CSS (สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับคลาสต่างๆ โปรดดูหัวข้อด้านล่าง) CssInliner
และคลาสการประมวลผล HTML ทั้งหมดสามารถใช้อินสแตนซ์ DOMDocument
เดียวกันเพื่อใช้งาน:
use Pelago Emogrifier CssInliner ;
use Pelago Emogrifier HtmlProcessor CssToAttributeConverter ;
use Pelago Emogrifier HtmlProcessor HtmlPruner ;
…
$ cssInliner = CssInliner:: fromHtml ( $ html )-> inlineCss ( $ css );
$ domDocument = $ cssInliner -> getDomDocument ();
HtmlPruner:: fromDomDocument ( $ domDocument )-> removeElementsWithDisplayNone ()
-> removeRedundantClassesAfterCssInlined ( $ cssInliner );
$ finalHtml = CssToAttributeConverter:: fromDomDocument ( $ domDocument )
-> convertCssToVisualAttributes ()-> render ();
คลาส HtmlNormalizer
ทำให้ HTML ที่กำหนดเป็นมาตรฐานด้วยวิธีต่อไปนี้:
สามารถใช้คลาสได้ดังนี้:
use Pelago Emogrifier HtmlProcessor HtmlNormalizer ;
…
$ cleanHtml = HtmlNormalizer:: fromHtml ( $ rawHtml )-> render ();
CssToAttributeConverter
จะแปลงค่าแอตทริบิวต์สไตล์บางส่วนเป็นแอตทริบิวต์ HTML แบบภาพ ซึ่งช่วยให้ได้รูปลักษณ์อย่างน้อยเล็กน้อยสำหรับโปรแกรมรับส่งเมลที่ไม่รองรับ CSS เป็นอย่างดี ตัวอย่างเช่น style="width: 100px"
จะถูกแปลงเป็น width="100"
สามารถใช้คลาสได้ดังนี้:
use Pelago Emogrifier HtmlProcessor CssToAttributeConverter ;
…
$ visualHtml = CssToAttributeConverter:: fromHtml ( $ rawHtml )
-> convertCssToVisualAttributes ()-> render ();
คุณยังสามารถให้ CssToAttributeConverter
ทำงานบน DOMDocument
:
$ visualHtml = CssToAttributeConverter:: fromDomDocument ( $ domDocument )
-> convertCssToVisualAttributes ()-> render ();
คลาส CssVariableEvaluator
สามารถใช้เพื่อใช้ค่าของตัวแปร CSS ที่กำหนดไว้ในแอตทริบิวต์สไตล์อินไลน์กับคุณสมบัติสไตล์อินไลน์ที่ใช้ตัวแปรเหล่านั้น
ตัวอย่างเช่น CSS ต่อไปนี้กำหนดและใช้คุณสมบัติที่กำหนดเอง:
: root {
--text-color : green;
}
p {
color : var ( --text-color );
}
หลังจากที่ CssInliner
ได้แทรก CSS นั้นไว้ใน HTML (ที่วางแผนไว้) <html><body><p></p></body></html>
จะมีลักษณะดังนี้:
< html style =" --text-color: green; " >
< body >
< p style =" color: var(--text-color); " >
< p >
</ body >
</ html >
วิธีการ CssVariableEvaluator
evaluateVariables
จะใช้ค่าของ --text-color
เพื่อให้แอตทริบิวต์ style
ย่อหน้ากลายเป็น color: green;
-
มันสามารถใช้ได้เช่นนี้:
use Pelago Emogrifier HtmlProcessor CssVariableEvaluator ;
…
$ evaluatedHtml = CssVariableEvaluator:: fromHtml ( $ html )
-> evaluateVariables ()-> render ();
คุณยังสามารถให้ CssVariableEvaluator
ทำงานบน DOMDocument
ได้ :
$ evaluatedHtml = CssVariableEvaluator:: fromDomDocument ( $ domDocument )
-> evaluateVariables ()-> render ();
คลาส HtmlPruner
สามารถลดขนาดของ HTML โดยการลบองค์ประกอบที่มี display: none
การประกาศสไตล์ และ/หรือลบคลาสออกจากแอตทริบิวต์ class
ที่ไม่จำเป็น
มันสามารถใช้ได้เช่นนี้:
use Pelago Emogrifier HtmlProcessor HtmlPruner ;
…
$ prunedHtml = HtmlPruner:: fromHtml ( $ html )-> removeElementsWithDisplayNone ()
-> removeRedundantClasses ( $ classesToKeep )-> render ();
วิธีการ removeRedundantClasses
ยอมรับรายการที่อนุญาตของชื่อของคลาสที่ควรเก็บไว้ หากนี่เป็นขั้นตอนหลังการประมวลผลหลังจากอินไลน์ CSS คุณสามารถใช้อีกวิธีหนึ่งคือ removeRedundantClassesAfterCssInlined
โดยส่งผ่านอินสแตนซ์ CssInliner
ที่ได้อินไลน์ CSS (และให้ HtmlPruner
ทำงานบน DOMDocument
) สิ่งนี้จะใช้ข้อมูลจาก CssInliner
เพื่อพิจารณาว่าคลาสใดที่ยังคงต้องการ (กล่าวคือ คลาสที่ใช้ในกฎที่ไม่สามารถควบคุมได้ซึ่งถูกคัดลอกไปยังองค์ประกอบ <style>
):
$ prunedHtml = HtmlPruner:: fromDomDocument ( $ cssInliner -> getDomDocument ())
-> removeElementsWithDisplayNone ()
-> removeRedundantClassesAfterCssInlined ( $ cssInliner )-> render ();
เมธอด removeElementsWithDisplayNone
จะไม่ลบองค์ประกอบใดๆ ที่มีคลาส -emogrifier-keep
ตัวอย่างเช่น หากมีองค์ประกอบที่โดยค่าเริ่มต้นมี display: none
แต่ถูกเปิดเผยโดยกฎ @media
หรือที่ตั้งใจให้เป็นส่วนหัวล่วงหน้า คุณสามารถเพิ่มคลาสนั้นให้กับองค์ประกอบเหล่านั้นได้ ย่อหน้าในตัวอย่าง HTML นี้จะไม่ถูกลบแม้ว่าจะมี display: none
(ซึ่งน่าจะถูกนำมาใช้โดย CssInliner::inlineCss()
จากกฎ CSS .preheader { display: none; }
):
< p class =" preheader -emogrifier-keep " style =" display: none; " >
Hello World!
</ p >
เมธอด removeRedundantClassesAfterCssInlined
(หรือ removeRedundantClasses
) หากถูกเรียกใช้หลังจาก removeElementsWithDisplayNone
จะลบคลาส -emogrifier-keep
ออก
มีหลายตัวเลือกที่คุณสามารถตั้งค่าบนอินสแตนซ์ CssInliner
ก่อนที่จะเรียกใช้เมธอด inlineCss
:
->disableStyleBlocksParsing()
- ตามค่าเริ่มต้น CssInliner
จะดึงบล็อก <style>
ทั้งหมดใน HTML และจะใช้สไตล์ CSS เป็นแอตทริบิวต์ "style" แบบอินไลน์กับ HTML บล็อก <style>
จะถูกลบออกจาก HTML หากคุณต้องการปิดการใช้งานฟังก์ชันนี้เพื่อให้ CssInliner
ออกจากบล็อก <style>
เหล่านี้ใน HTML และไม่แยกวิเคราะห์ คุณควรใช้ตัวเลือกนี้ หากคุณใช้ตัวเลือกนี้ เนื้อหาของบล็อก <style>
จะ ไม่ ถูกนำมาใช้เป็นรูปแบบอินไลน์ และ CSS ใดๆ ที่คุณต้องการให้ CssInliner
ใช้จะต้องส่งผ่านตามที่อธิบายไว้ในส่วนการใช้งานด้านบน->disableInlineStyleAttributesParsing()
- ตามค่าเริ่มต้น CssInliner
จะรักษาแอตทริบิวต์ "style" ทั้งหมดบนแท็กใน HTML ที่คุณส่งไป อย่างไรก็ตาม หากคุณต้องการละทิ้งสไตล์อินไลน์ที่มีอยู่ใน HTML ก่อนที่จะใช้ CSS คุณควรใช้ตัวเลือกนี้->addAllowedMediaType(string $mediaName)
- ตามค่าเริ่มต้น CssInliner
จะเก็บเฉพาะประเภทสื่อ all
, screen
และ print
หากคุณต้องการเก็บบางรายการไว้ คุณสามารถใช้วิธีนี้เพื่อกำหนดรายการเหล่านั้นได้->removeAllowedMediaType(string $mediaName)
- คุณสามารถใช้วิธีนี้เพื่อลบประเภทสื่อที่ Emogrifier เก็บไว้ได้->addExcludedSelector(string $selector)
- ป้องกันไม่ให้องค์ประกอบได้รับผลกระทบจากการแทรก CSS โปรดทราบว่าเฉพาะองค์ประกอบที่ตรงกับตัวเลือกที่ให้มาเท่านั้นที่จะถูกแยกออกจาก CSS inline โดยไม่จำเป็นต้องเป็นองค์ประกอบที่สืบทอด หากคุณต้องการยกเว้นแผนผังย่อยทั้งหมด คุณควรระบุตัวเลือกที่จะจับคู่องค์ประกอบทั้งหมดในแผนผังย่อย เช่น โดยใช้ตัวเลือกสากล: $ cssInliner -> addExcludedSelector ( ' .message-preview ' );
$ cssInliner -> addExcludedSelector ( ' .message-preview * ' );
->addExcludedCssSelector(string $selector)
- ตรงกันข้ามกับ addExcludedSelector
ซึ่งไม่รวมโหนด HTML เมธอดนี้จะไม่รวมตัวเลือก CSS จากการถูกอินไลน์ ตัวอย่างนี้มีประโยชน์ หากคุณไม่ต้องการให้กฎการรีเซ็ต CSS อยู่ในบรรทัดในแต่ละโหนด HTML (เช่น * { margin: 0; padding: 0; font-size: 100% }
) โปรดทราบว่าตัวเลือกเหล่านี้จะต้องตรงกับตัวเลือกที่คุณต้องการยกเว้นทุกประการ หมายความว่าการยกเว้น .example
จะไม่ยกเว้น p .example
$ cssInliner -> addExcludedCssSelector ( ' * ' );
$ cssInliner -> addExcludedCssSelector ( ' form ' );
->removeExcludedCssSelector(string $selector)
- ลบตัวเลือกที่ยกเว้นที่เพิ่มไว้ก่อนหน้านี้ ถ้ามี $ cssInliner -> removeExcludedCssSelector ( ' form ' );
Emogrifier
ที่ดร็อปไปเป็นคลาส CssInliner
รหัสเก่าที่ใช้ Emogrifier
:
$ emogrifier = new Emogrifier ( $ html );
$ html = $ emogrifier -> emogrify ();
รหัสใหม่โดยใช้ CssInliner
:
$ html = CssInliner:: fromHtml ( $ html )-> inlineCss ()-> render ();
หมายเหตุ: ในตัวอย่างนี้ โค้ดเก่าจะลบองค์ประกอบที่มี display: none;
ในขณะที่โค้ดใหม่ไม่มี เนื่องจากพฤติกรรมเริ่มต้นของคลาสเก่าและคลาสใหม่แตกต่างกันในเรื่องนี้
รหัสเก่าที่ใช้ Emogrifier
:
$ emogrifier = new Emogrifier ( $ html , $ css );
$ emogrifier -> enableCssToHtmlMapping ();
$ html = $ emogrifier -> emogrify ();
รหัสใหม่โดยใช้ CssInliner
และตระกูล:
$ domDocument = CssInliner:: fromHtml ( $ html )-> inlineCss ( $ css )-> getDomDocument ();
HtmlPruner:: fromDomDocument ( $ domDocument )-> removeElementsWithDisplayNone ();
$ html = CssToAttributeConverter:: fromDomDocument ( $ domDocument )
-> convertCssToVisualAttributes ()-> render ();
ปัจจุบัน Emogrifier รองรับตัวเลือก CSS ต่อไปนี้:
~
(หนึ่งคำภายในรายการคำที่คั่นด้วยช่องว่าง)|
(ค่าที่ตรงกันทุกประการหรือคำนำหน้าตามด้วยยัติภังค์)^
(การจับคู่คำนำหน้า)$
(การจับคู่คำต่อท้าย)*
(การจับคู่สตริงย่อย)p:first-of-type
แต่ไม่ใช่ *:first-of-type
)ตัวเลือกต่อไปนี้ยังไม่ได้ใช้งาน:
<style>
ใน HTML - รวมถึง (แต่ไม่จำกัดเพียง) สิ่งต่อไปนี้: กฎที่เกี่ยวข้องกับตัวเลือกต่อไปนี้ไม่สามารถใช้เป็นรูปแบบอินไลน์ได้ อย่างไรก็ตาม พวกเขาจะถูกเก็บรักษาและคัดลอกไปยังองค์ประกอบ <style>
ใน HTML:
:hover
)::after
) @media
ที่เกี่ยวข้องทั้งหมด การสืบค้นสื่อมีประโยชน์มากในการออกแบบอีเมลที่ตอบสนอง ดูการสนับสนุนการสืบค้นสื่อ อย่างไรก็ตาม เพื่อให้มีประสิทธิภาพ คุณอาจต้องเพิ่ม !important
ในการประกาศบางส่วนภายในประกาศเหล่านั้น เพื่อที่การประกาศเหล่านี้จะแทนที่สไตล์ CSS ที่ฝังไว้ ตัวอย่างเช่น ด้วย CSS ต่อไปนี้ การประกาศ font-size
ในกฎ @media
จะไม่แทนที่ขนาดแบบอักษรสำหรับองค์ประกอบ p
จากกฎก่อนหน้า หลังจากนั้นถูกแทรกในบรรทัดเป็น <p style="font-size: 16px;">
ใน HTML โดยไม่มี !important
คำสั่ง (แม้ว่า !important
จะไม่จำเป็นหาก CSS ไม่ได้อยู่ในบรรทัด): p {
font-size : 16 px ;
}
@media ( max-width : 640 px ) {
p {
font-size : 14 px !important ;
}
}
@media
ไม่สามารถใช้กับค่าคุณสมบัติ CSS ที่ได้รับการอินไลน์และประเมินผลได้ อย่างไรก็ตาม กฎ @media
ที่ใช้คุณสมบัติที่กำหนดเอง (ด้วย var()
) จะยังคงสามารถรับค่าได้ (จากคำจำกัดความในบรรทัดหรือกฎ @media
) ในไคลเอนต์อีเมลที่รองรับคุณสมบัติที่กำหนดเอง::after
) หรือคลาสหลอกแบบไดนามิก (เช่น :hover
) - มันเป็นไปไม่ได้ อย่างไรก็ตาม กฎดังกล่าวจะถูกเก็บรักษาและคัดลอกไปยังองค์ประกอบ <style>
เช่นเดียวกับกฎ @media
โดยจะมีการใช้คำเตือนเดียวกัน<style>
จาก HTML ของคุณ แต่จะไม่ดึงไฟล์ CSS ที่อ้างอิงในองค์ประกอบ <link>
หรือกฎ @import
(แม้ว่าจะปล่อยให้บล็อกเหล่านั้นไม่เสียหายสำหรับไคลเอนต์อีเมลที่รองรับ)โปรดดูที่ API และนโยบายการเลิกใช้งานของเรา
การมีส่วนร่วมในรูปแบบของรายงานข้อผิดพลาด คำขอคุณสมบัติ หรือคำขอดึงข้อมูลเป็นสิ่งที่น่ายินดีเป็นอย่างยิ่ง โปรดดูแนวทางการมีส่วนร่วมของเราเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการมีส่วนร่วมกับ Emogrifier
branch-alias
ให้ชี้ไปที่การเปิดตัว หลังจาก การเปิดตัวที่กำลังจะมาถึง