Post pobrano z: e-Types![]()
Archiwum kategorii: CSS
ShopTalk 250: Web Security
Post pobrano z: ShopTalk 250: Web Security
For all y’all that want to understand the potential attacks, and potential defenses, of front-end web development.
It’s pretty wild. The dangers are big, real, and many. But the tools we have to fight back are up to the job, we just need to know about them and use them.
Direct Link to Article — Permalink
ShopTalk 250: Web Security is a post from CSS-Tricks
Lamy Lexel – Voeux 2017
Post pobrano z: Lamy Lexel – Voeux 2017![]()
The Darling Oyster Bar
Post pobrano z: The Darling Oyster Bar![]()
Subform
Post pobrano z: Subform![]()
Creating Non-Rectangular Headers
Post pobrano z: Creating Non-Rectangular Headers
Over at Medium, Jon Moore recently identified „non-rectangular headers” as a tiny trend. A la: it’s not crazy popular yet, but just you wait, kiddo.
We’re talking about headers (or, more generally, any container element) that have a non-rectangular shape.
Such as trapezoids:

Or more complex geometric shapes:


Or rounded/elliptical:

Or even butt-cheek shaped:

My money is on these gaining popularity too. So let’s beat the crowd, and talk about a few ways of coding these up. Because let’s face it: they do look pretty awesome.
Image
Perhaps the simplest way to create any of the non-rectangular headers pictured above is to slap an image on top of your header.
See the Pen Image file-based non-rectangular header by Erik Kennedy (@erikdkennedy) on CodePen.
But there are a few issues here:
- Responsive behavior? These masks tend to be full-width, and it becomes tedious to define multiple widths of the shape (e.g. srcset) or risk pixelation of raster assets.
- It’s a totally separate file that needs to be fetched from the server – seems wasteful for simple shapes.
- It’s slow to iterate in-browser if you have to re-export an image file(s) from your design program.
We can solve all of these problems at once. You might already know where this one is going.
SVG
Compared to exporting a JPG from Sketch, using an inline SVG is more performant, easy to make responsive, and easy to iterate the design of. In fact, for most cases, this is the way I’d recommend using. Versatile, cross-browser, vector, and fabulous.
See the Pen SVG trapezoidal header by Erik Kennedy (@erikdkennedy) on CodePen.
With an angled background one like, one choice you have to make is: what should remain constant as the screen-width changes, the angle or the height differential between the two sides?
If you want the angle to remain constant, set the height of the SVG in vw:

If you want the height differential to remain constant, set the height of the SVG in pixels:

And you need not pick just one – we can style this responsively, since SVG elements are subject to media queries. Check out this geometric style header at widths below and above 700px.
See the Pen Responsive SVG header by Erik Kennedy (@erikdkennedy) on CodePen.
Shoot, son. What’s not to love? Oh, and we can even do the butt-cheeks style.
See the Pen SVG „butt-cheeks” header by Erik Kennedy (@erikdkennedy) on CodePen.
(Perhaps that’s more properly done with beziers, but you get the idea!)
One more thing worth nothing, and that is if you want to do an SVG background entirely in CSS, you could save the SVG and reference its URL in a pseudo element.
header::after {
content: "";
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
background: url(divider.svg);
}
And if you use `divider.svg` as a repeating element in different scenarios, you can also color it different as you need:
header::after polygon {
fill: white;
}
But here’s an issue: what if the section below the header has a complicated background? In all these examples so far, we’ve just assumed a plain white background. What if there’s a fancy gradient, or another background image or something? Then what?
clip-path
This property comes to the rescue if you have a moderately complex background below the header, and therefore want the masking to be done from within the non-rectangular header, as opposed to by an element after it.
See the Pen Non-Rectangular Header Using Clip-Path by Erik Kennedy (@erikdkennedy) on CodePen.
And like the similar SVG syntax, if you want to change the responsive behavior of the above from angle-is-held-constant to height-differential-is-held-constant, you can change the calculated height to a simple percentage.
Clip-path’s biggest downside? Browser support is not that great. However, depending on how important your non-rectangular header or div is, it might qualify as a progressive enhancement. In which case, clip-path away!
border-radius
Now, up to now, we’ve only mentioned methods that work for generating all the shapes I called out above. However, if we know what particular shape we want our header to have, we might have access to an easier way.
For instance, a convex elliptical header is a perfect fit for border-radius.
See the Pen Convex elliptical header by Erik Kennedy (@erikdkennedy) on CodePen.
And a concave elliptical header could simply have the border-radius on the element after the header.
section {
border-bottom-left-radius: 50% 20%;
border-bottom-right-radius: 50% 20%;
}
Another benefit to this method is that the background of the section below the header could still have background images.
transform: skew
If we know that we want to create do a trapezoidal header, we can use a CSS transform to skew the whole thing.
See the Pen Trapezoid Header Using Transform: SkewY by Erik Kennedy (@erikdkennedy) on CodePen.
This has the side effect of skewing any child elements of the skewed element, so you’ll want to add a child element in the header that gets skewed, and everything else will go in sibling elements.


Stripe’s homepage design uses this method, and even more brilliantly, they include a few children spans (each is a block of color) that get skewed with the parent element, creating a more complex and colorful effect.
Which is best?
As far as I’m concerned, SVG is generally the way to go. However, if you have a more complex background below the header, then the best choice depends on the shape. In that case, I’d investigate if skew or border-radius could meet the art direction needed, or if browser support was enough of a non-issue to go with clip-path.
| Allows complex BG below | Browser support | Shapes creatable | |
|---|---|---|---|
| Image | No | Yes | All |
| SVG | No | Yes | All |
| Clip-path | Yes | No | All |
| Border-radius | Yes | Yes | Elliptical only |
| Transform: skew | Yes | Yes | Trapezoidal only |
Erik Kennedy is an independent UX/UI designer and the creator of Learn UI Design, a practical online video course about visual design for screens. Includes color, typography, process, and more. Over 16 hours of video across 30+ lessons.
Creating Non-Rectangular Headers is a post from CSS-Tricks
Most of the web really sucks if you have a slow connection
Post pobrano z: Most of the web really sucks if you have a slow connection
Dan Luu on the sorry state of web performance:
…it’s not just nerds like me who care about web performance. In the U.S., AOL alone had over 2 million dialup users in 2015. Outside of the U.S., there are even more people with slow connections.
This other note is also interesting, and I think that Dan is talking about Youtube’s project “Feather” here:
When I was at Google, someone told me a story about a time that “they” completed a big optimization push only to find that measured page load times increased. When they dug into the data, they found that the reason load times had increased was that they got a lot more traffic from Africa after doing the optimizations. The team’s product went from being unusable for people with slow connections to usable, which caused so many users with slow connections to start using the product that load times actually increased.
Direct Link to Article — Permalink
Most of the web really sucks if you have a slow connection is a post from CSS-Tricks
What Really Makes a Static Site Generator?
Post pobrano z: What Really Makes a Static Site Generator?
I talk a lot about static site generators, but always about using static site generators. In most cases, it may seem like a black box. I create a template and some Markdown and out comes a fully formed HTML page. Magic!
But what exactly is a static site generator? What goes on inside that black box? What kind of voodoo is this?
In this post, I want to explore all of the parts that make up a static site generator. First, we’ll discuss these in a general fashion, but then we’ll take a closer look at some actual code by delving deep inside HarpJS. So, put your adventurer’s cap on and let’s start exploring.
Why Harp? For two reasons. The first is that HarpJS is, by design, a very simple static site generator. It doesn’t have a lot of the features that might cause us to get lost exploring a more comprehensively full-featured static site generator (like Jekyll for instance). The second, much more practical, reason is that I know JavaScript and don’t know Ruby very well.
The Basics of a Static Site Generator
The truth is, a static site generator is a pretty simple concept. The key ingredients to a static site generator are typically:
- A template language(s) for creating page/post templates
- A lightweight markup language (typically Markdown) for authoring content
- A structure and markup (often YAML) for providing configuration and metadata (e.g. „front matter„)
- A set of rules or structure for organizing and naming files that are exported/compiled, files that are not and how these files will be handled (e.g. frequently prefacing a file or folder with an underscore means that it is not exported into the final site files or all posts go in a posts folder)
- A means of compiling templates and markup into HTML (frequently support for CSS or JavaScript preprocessors is also included)
- A local server for testing.
That’s it. If you’re thinking, „Hey… I could build that!” you are probably correct. Things start to get complicated though when you start to expand the functionality, as most static site generators do.
So, let’s look at how Harp handles this.
Getting to the Harp of the Matter
Let’s look at the basics of how Harp handles the key ingredients described above. Harp offers more than this handful of functionality, but, for the sake of our examination, we’ll stick to those items.
First, let’s discuss the basics of Harp.
Harp Basics
Harp supports Jade and EJS (for templating) and Markdown as its lightweight markup language (for content). Note that while Jade is now called Pug, Harp has not officially transitioned in their documentation or code, so we’ll stick with Jade here. Harp also offers support for other preprocessing such as Less, Sass, and Stylus for CSS and CoffeeScript for JavaScript.
By default Harp does not require much in the way of configuration or metadata. It tends to favor convention over configuration. However, it allows for specific metadata and configuration using JSON. It differs from many other static site generators in that file metadata is contained outside of the actual file within a `_data.json` file.
While it is configurable to a degree, Harp has certain established guidelines for how to structure files. For example, in a typical application, the files that are served fall within a public directory. Also, any file or folder prefaced by an underscore will not be served.
Lastly, Harp offers a basic local web server for testing that includes some configurable options. And, of course, it will compile the finished HTML, CSS and JavaScript files for deployment.
Let’s Look at Harp’s Actual Source Code
Since much of what makes a static site generator are rules and conventions, the code centers around the actual serving and compiling (for the most part). Let’s dig in.
The Server Function
In Harp, serving your project is usually done by executing harp server from the command line. Let’s look at the code for that function:
exports.server = function(dirPath, options, callback){
var app = connect()
app.use(middleware.regProjectFinder(dirPath))
app.use(middleware.setup)
app.use(middleware.basicAuth)
app.use(middleware.underscore)
app.use(middleware.mwl)
app.use(middleware.static)
app.use(middleware.poly)
app.use(middleware.process)
app.use(middleware.fallback)
return app.listen(options.port || 9966, options.ip, function(){
app.projectPath = dirPath
callback.apply(app, arguments)
})
}
While the function looks simple, obviously there is a ton going on within middleware that isn’t illustrated here.
The rest of this function opens up a server with the options you specify (if any). Those options include a port, an IP to bind to and a directory. By default the port is 9000 (not 9966 as you might guess by the code), the directory is the current one (i.e. the one Harp is running in) and the IP is 0.0.0.0.
The Compiler Function
Staying within index.js, let’s take a look at the compile function next.
exports.compile = function(projectPath, outputPath, callback){
/**
* Both projectPath and outputPath are optional
*/
if(!callback){
callback = outputPath
outputPath = "www"
}
if(!outputPath){
outputPath = "www"
}
/**
* Setup all the paths and collect all the data
*/
try{
outputPath = path.resolve(projectPath, outputPath)
var setup = helpers.setup(projectPath, "production")
var terra = terraform.root(setup.publicPath, setup.config.globals)
}catch(err){
return callback(err)
}
/**
* Protect the user (as much as possible) from compiling up the tree
* resulting in the project deleting its own source code.
*/
if(!helpers.willAllow(projectPath, outputPath)){
return callback({
type: "Invalid Output Path",
message: "Output path cannot be greater then one level up from project path and must be in directory starting with `_` (underscore).",
projectPath: projectPath,
outputPath: outputPath
})
}
/**
* Compile and save file
*/
var compileFile = function(file, done){
process.nextTick(function () {
terra.render(file, function(error, body){
if(error){
done(error)
}else{
if(body){
var dest = path.resolve(outputPath, terraform.helpers.outputPath(file))
fs.mkdirp(path.dirname(dest), function(err){
fs.writeFile(dest, body, done)
})
}else{
done()
}
}
})
})
}
/**
* Copy File
*
* TODO: reference ignore extensions from a terraform helper.
*/
var copyFile = function(file, done){
var ext = path.extname(file)
if(!terraform.helpers.shouldIgnore(file) && [".jade", ".ejs", ".md", ".styl", ".less", ".scss", ".sass", ".coffee"].indexOf(ext) === -1){
var localPath = path.resolve(outputPath, file)
fs.mkdirp(path.dirname(localPath), function(err){
fs.copy(path.resolve(setup.publicPath, file), localPath, done)
})
}else{
done()
}
}
/**
* Scan dir, Compile Less and Jade, Copy the others
*/
helpers.prime(outputPath, { ignore: projectPath }, function(err){
if(err) console.log(err)
helpers.ls(setup.publicPath, function(err, results){
async.each(results, compileFile, function(err){
if(err){
callback(err)
}else{
async.each(results, copyFile, function(err){
setup.config['harp_version'] = pkg.version
delete setup.config.globals
callback(null, setup.config)
})
}
})
})
})
}
The first portion defines the output path as specified by the call to harp compile via the command line (source here). The default, as you can see, is www. The callback is a callback function passed by the command line utility which is not configurable.
The next part starts by calling the setup function in the helpers module. For the sake of brevity, we won’t go into the specific code of the function (feel free to look for yourself), but essentially it reads the site configuration (i.e. harp.json).
You may also notice a call to something called terraform. This will come up again within this function. Terraform is actually a separate project required by Harp that is the basis of its asset pipeline. The asset pipeline is where the hard work of compiling and building the finished site gets done (we’ll look at Terraform code in a little bit).
The next portion of code, as it states, tries to prevent you from specifying an output directory that would inadvertently overwrite your source code (which would be bad as you’d lose any work since your last commit).
The compileFile and copyFile functions are fairly self-explanatory. The compileFile function relies on Terraform to do the actual compilation. Both of these functions drive the prime function which uses a helper function (fs) to walk the directories, compiling or copying files as necessary in the process.
Terraform
As I discussed, Terraform does the grunt work for compiling the Jade, Markdown, Sass and CoffeeScript into HTML, CSS and JavaScript (and assembling these pieces as defined by Harp). Terraform is made up of a number of files that define its processors for JavaScript, CSS/stylesheets, and templates (which, in this case, includes Markdown).

Within each of these folders is a processors folder that contains the code for each specific processor that Terraform (i.e. Harp) supports. For example, in the templates folder are files that form the basis for compiling EJS, Jade, and Markdown files.

I won’t delve into the code for each of these, but, for the most part, they rely upon external npm modules that handle the supported processor. For example, for Markdown support, it depends upon Marked.
The core logic of Terraform is contained in its render function.
/**
* Render
*
* This is the main method to to render a view. This function is
* responsible to for figuring out the layout to use and sets the
* `current` object.
*
*/
render: function(filePath, locals, callback){
// get rid of leading slash (windows)
filePath = filePath.replace(/^\\/g, '')
// locals are optional
if(!callback){
callback = locals
locals = {}
}
/**
* We ignore files that start with underscore
*/
if(helpers.shouldIgnore(filePath)) return callback(null, null)
/**
* If template file we need to set current and other locals
*/
if(helpers.isTemplate(filePath)) {
/**
* Current
*/
locals._ = lodash
locals.current = helpers.getCurrent(filePath)
/**
* Layout Priority:
*
* 1. passed into partial() function.
* 2. in `_data.json` file.
* 3. default layout.
* 4. no layout
*/
// 1. check for layout passed in
if(!locals.hasOwnProperty('layout')){
// 2. _data.json layout
// TODO: Change this lookup relative to path.
var templateLocals = helpers.walkData(locals.current.path, data)
if(templateLocals && templateLocals.hasOwnProperty('layout')){
if(templateLocals['layout'] === false){
locals['layout'] = null
} else if(templateLocals['layout'] !== true){
// relative path
var dirname = path.dirname(filePath)
var layoutPriorityList = helpers.buildPriorityList(path.join(dirname, templateLocals['layout'] || ""))
// absolute path (fallback)
layoutPriorityList.push(templateLocals['layout'])
// return first existing file
// TODO: Throw error if null
locals['layout'] = helpers.findFirstFile(root, layoutPriorityList)
}
}
// 3. default _layout file
if(!locals.hasOwnProperty('layout')){
locals['layout'] = helpers.findDefaultLayout(root, filePath)
}
// 4. no layout (do nothing)
}
/**
* TODO: understand again why we are doing this.
*/
try{
var error = null
var output = template(root, templateObject).partial(filePath, locals)
}catch(e){
var error = e
var output = null
}finally{
callback(error, output)
}
}else if(helpers.isStylesheet(filePath)){
stylesheet(root, filePath, callback)
}else if(helpers.isJavaScript(filePath)){
javascript(root, filePath, callback)
}else{
callback(null, null)
}
}
(If you were reading all this code closely, you likely noticed TODO’s, typos, and even a funny „understand again why we are doing this” comment. That’s real life coding!)
The majority of the code in the render function is about handling templates. Things like CoffeeScript and Sass fundamentally render on a one-to-one basis. For example, style.scss will render to style.css. Even if it has includes, that is handled by the renderer. The very end of the render function deals with these types of files.
Layouts in Harp, on the other hand, are nested within each other in a variety of manners that can even depend upon configuration. For example, about.md might be rendered within the default _layout.jade (where, exactly, is determined by the use of != yield within that layout). However, _layout.jade might include multiple other layouts within itself by way of the partial support in Harp.
Partials are a way of splitting up a template into multiple files. They are especially useful for code reuse. For instance, I might put the site header inside a partial. Partials are important for making layouts within a static site generator maintainable but they also add a good deal of complexity to the logic of compiling templates. This complexity is handled within the partial function of the templates processor.
Finally, you could override the default layout by specifying a specific layout or no layout at all for a particular file within the _data.json configuration file. All of these scenarios are handled (and even numbered) within the logic of the render function.
That’s Not So Complicated, Is It?
To make this digestible, I’ve skipped over a ton of additional detail. At its core, every static site generator I’ve ever used (and I’ve used a bunch) functions similarly: a set of rules, conventions, and configuration that is run through compilers for the various supported markups. Perhaps that is why there are a ridiculous number of static site generators out there.
That being said, I wouldn’t want to build my own!
My Report & Book
If you are interested in learning how to build sites using a static site generator, I’ve authored a report and co-authored a book for O’Reilly that might interest you. My report, simply titled Static Site Generators is free and attempts to establish the history, landscape, and basics behind static site generators.

The book that I co-authored with Raymond Camden is called Working with Static Sites and is available as an early release, but should be available in print soon.
What Really Makes a Static Site Generator? is a post from CSS-Tricks
This browser tweak saved 60% of requests to Facebook
Post pobrano z: This browser tweak saved 60% of requests to Facebook
Ben Maurer & Nate Schloss:
The browser’s reload button exists to allow the user to get an updated version of the current page. In order to meet this goal, when you reload, browsers revalidate the page that you are currently on, even if that page hasn’t expired yet. However, they also go a step further and revalidate all sub-resources on the page — things like images and JavaScript files.
So even if you’ve set proper expires headers for resources, hitting that reload button (which people must do a ton at Facebook) still requires server round trips to revalidate assets (sometimes).
They worked with Chrome:
After fixing this, Chrome went from having 63% of its requests being conditional to 24% of them being conditional.
And Firefox:
Firefox implemented a proposal from one of our engineers to add a new cache-control header for some resources in order to tell the browser that this resource should never be revalidated.
So if you’re using URLs for assets that never change (if they change, they’ll be at a new URL) in Chrome you’ll benefit automatically, and in Firefox you should use their new header.
Direct Link to Article — Permalink
This browser tweak saved 60% of requests to Facebook is a post from CSS-Tricks
Basic Shapes & Path… Never the Twain Shall Meet?
Post pobrano z: Basic Shapes & Path… Never the Twain Shall Meet?
There are some values available in CSS that allow shapes to be drawn. For example, there is a circle() function that is a valid value for a couple of CSS properties. „Drawn” might not be the right word, though. It’s not like in SVG where you can create a <circle> element and it will literally draw a circle.
These shapes in CSS are for other things. Namely: clip-path, which is for making clipping masks, and shape-outside, for flowing text around shapes.
There are some other CSS properties that use SVG-like shapes for doing what they do. For example, offset-path is part of animating elements along vector paths, using the path() function. Paths are awesome. They are the ultimate drawing element, as they can draw anything, and all the other shapes are essentially syntactic sugar for paths.
What are the basic shapes?
There are four basic shapes:
polygon()circle()ellipse()inset()
What are paths?
Paths come from SVG. They have a special syntax that allows them to draw anything.
<path d="M 25,100 C 25,150 75,150 75,100 S 100,25 150,75" />
path("M 25,100 C 25,150 75,150 75,100 S 100,25 150,75");
This is where things get kinda weird
- The
clip-pathandshape-outsideproperties can take all the „basic shapes” likecircle()andpolygon(), but notpath(). - The
offset-pathproperties can takepath(), but not the „basic shapes”. - You can control the
dattribute of a<path>through CSS also, but not the attributes of many other SVG elements.
I’m not really sure why any of this is, and I’m sure things will change in time, but it’s good to know about.
Let’s elaborate.
clip-path allows Basic Shapes (but not path())
Say you wanted to clip square avatars into polygons, for a fun design. You can! The image is might be an HTML element like:
<img src="avatar.jpg" alt="User Avatar" class="avatar">
.avatar {
clip-path: polygon(0% 5%, 100% 0%, 100% 85%, 65% 80%, 75% 100%, 40% 80%, 0% 75%);
}
See the Pen Clipped Avatars by Chris Coyier (@chriscoyier) on CodePen.
But let’s say you want to clip the avatar like this:

Well, you can’t. Not directly in CSS anyway. Those curves require a path, and clip-path don’t do path. Fortunatly, clip-path does take a url(), which will accept the ID of a <clipPath> element.
See the Pen Clipped Avatars by Chris Coyier (@chriscoyier) on CodePen.
offset-path allows path (but not Basic Shapes)
Say we want to move an object along the outside of that speech bubble shape we just used. The offset-path property is just for that.
<div class="move-me"></div>
.move-me {
offset-path: path("M100.5,39.47C100.5,58.3,83.36,74,60.58,77.64l16.85,19.9L33.94,76.25C14.47,70.92.5,56.47.5,39.47c0-21.52,22.39-39,50-39S100.5,17.95,100.5,39.47Z");
animation: move 3s linear infinite;
}
@keyframes move {
100% { motion-offset: 100%;}
}
See the Pen offset-path on path by Chris Coyier (@chriscoyier) on CodePen.
But what if you want to move the element in a circle? The basic shape version of a circle has a super easy syntax, like circle(50% at 50% 50%); But unfortunately, the basic shapes aren’t supported. The spec allows for them, but they don’t work. It kinda makes sense, because… how would you define which direction to travel?
You can still animate in a circle, because the all-powerful path can draw a circle, like:
.move-me {
/* a circle */
offset-path: path("M100,50a50,50,0,1,1-50-50A50,50,0,0,1,100,50Z");
animation: move 3s linear infinite;
}
@keyframes move {
100% { motion-offset: 100%;}
}
And those commands dictate a direction naturally. There are also other ways to animate in a circle.
shape-outside allows Basic Shapes (but not path())
Say you wanted to wrap some text around an egg shape, because I dunno, you were setting some text of Alice talking to Humpty Dumpty. The egg shape is a good excuse to use the ellipse() Basic Shape.
<div class="page-wrap">
<div class="egg"></div>
<p>"I don't know what you mean by 'glory,'" Alice said.</p>
<p>Humpty Dumpty smiled contemptuously. "Of course you don't—till I tell you. I meant 'there's a nice knock-down argument for you!'"</p>
...
.egg {
float: left;
shape-outside: ellipse(120px 160px at 50% 50%);
width: 280px;
height: 320px;
}
We’d probably set an identical clip-path (to actually make the egg shape) and colorize it:
See the Pen Shape Outside Egg by Chris Coyier (@chriscoyier) on CodePen.
But what if you wanted to make some text wrap around a curved shape, like shown here in Illustrator:

Unfortunately, shape-outside doesn’t take path(), so you can’t. But you kinda can. It does take url(), in which you can use to link to an image (doesn’t even have to be SVG, but SVG makes good sense). The image can have a nice curvy path, like we’re shooting for:
See the Pen Wrap Text Around Curve by Chris Coyier (@chriscoyier) on CodePen.
The url() can even be a data URL. Also note that any element using shape-outside must be floated, a limitation that might be resolved with CSS Exclusions.
<path> takes path()
Here’s one that starts out making logical sense. Say you have a path:
<svg>
<path d=" ... " />
</svg>
You can change the shape of that path through CSS, say through a hover:
svg:hover path {
d: path(" ... ");
}
See the Pen Change path on hover by Chris Coyier (@chriscoyier) on CodePen.
You can even transition the shape, if it happens to be path data with the same amount of points.
It does get a bit confusing though. Say you have a <polygon> instead.
<svg>
<polygon points=" ... " />
</svg>
How do you update it with CSS?
polygon {
/* Nope */
points: " ... ";
/* Nope */
points: points(" ... ");
/* Nope */
points: polygon(" ... ");
}
There isn’t a way, that I know of. Which seems weird as polygon is otherwise supported all over the place. I imagine part of problem is that the polygon() function is different from the points attribute. The polygon() function takes percentages and numbers with units in CSS, whereas the points attribute takes unitless numbers (like everything in SVG). They are different beasts, and that overlap is awkward.
It’s also not that SVG shapes that overlap with Basic Shapes can’t be altered. All of <circle>’s attributes, for example, can be altered with CSS:
svg:hover circle {
cx: 40;
cy: 40;
r: 40;
}
See the Pen Altering Circle Attributes by Chris Coyier (@chriscoyier) on CodePen.
Long story short: there is usually a way to get done what you want to get done, but it’s confusing what is/isn’t supported where.
Basic Shapes & Path… Never the Twain Shall Meet? is a post from CSS-Tricks
