{"id":277034,"date":"2018-10-18T07:24:15","date_gmt":"2018-10-18T14:24:15","guid":{"rendered":"http:\/\/css-tricks.com\/?p=277034"},"modified":"2018-10-18T07:24:57","modified_gmt":"2018-10-18T14:24:57","slug":"svg-marching-ants","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/svg-marching-ants\/","title":{"rendered":"SVG Marching Ants"},"content":{"rendered":"

Maxim Leyzerovich created the marching ants effect<\/a> with some delectably simple SVG.<\/p>\n

<\/p>\n

See the Pen SVG Marching Ants<\/a> by Maxim Leyzerovich (@round<\/a>) on CodePen<\/a>.<\/p>\n

Let’s break it apart bit by bit and see all the little parts come together.<\/p>\n

Step 1: Draw a dang rectangle<\/h3>\n

We can set up our SVG like a square, but have the aspect ratio ignored and have it flex into whatever rectangle we’d like.<\/p>\n

<svg viewbox='0 0 40 40' preserveAspectRatio='none'>\r\n  <rect width='40' height='40' \/>\r\n<\/svg><\/code><\/pre>\n

Right away, we’re reminded that the coordinate system inside an SVG is unit-less. Here we’re saying, “This SVG is a 40x40<\/code> grid. Now draw a rectangle covering the entire grid.” We can still size the whole SVG in CSS though. Let’s force it to be exactly half of the viewport:<\/p>\n

svg {\r\n  position: absolute;\r\n  width: 50vw;\r\n  height: 50vh;\r\n  top: 0;\r\n  right: 0;\r\n  bottom: 0;\r\n  left: 0;\r\n  margin: auto;\r\n}<\/code><\/pre>\n

Step 2: Fight the squish<\/h3>\n

Because we made the box and grid so flexible, we’ll get some squishing that we probably could have predicted. Say we have a stroke that is 2<\/code> wide in our coordinate system. When the SVG is narrow, it still needs to split that narrow space into 40<\/code> units. That means the stroke will be quite narrow. <\/p>\n

rect {\r\n  fill: none;\r\n  stroke: #000;\r\n  stroke-width: 10px;\r\n  vector-effect: non-scaling-stroke;\r\n}<\/code><\/pre>\n

Now the stroke will behave more like a border on an HTML element.<\/p>\n

Step 3: Draw the cross lines<\/h3>\n

In Maxim’s demo, he draws the lines in the middle with four path elements. Remember, we have a 40x40<\/code> coordinate system, so the math is great:<\/p>\n

<path d='M 20,20 L 40,40' \/>\r\n<path d='M 20,20 L 00,40 '\/>\r\n<path d='M 20,20 L 40,0' \/>\r\n<path d='M 20,20 L 0,0' \/><\/code><\/pre>\n

These are four lines that start in the exact center (20,20<\/code>) and go to each corner. Why four lines instead of two that go corner to corner? I suspect it’s because the marching ants animation later looks kinda cooler if all the ants are emanating from the center rather than crisscrossing. <\/p>\n

I love the nice syntax of path<\/a>, but let’s only use two lines to be different:<\/p>\n

<line x1=\"0\" y1=\"0\" x2=\"40\" y2=\"40\"><\/line>\r\n<line x1=\"0\" y1=\"40\" x2=\"40\" y2=\"0\"><\/line><\/code><\/pre>\n

If we apply our stroke to both our rect<\/code> and line<\/code>, it works! But we see a slightly weird issue:<\/p>\n

rect, line {\r\n  fill: none;\r\n  stroke: #000;\r\n  stroke-width: 1px;\r\n  vector-effect: non-scaling-stroke;\r\n}<\/code><\/pre>\n
\"\"<\/figure>\n

The outside line appears thinner than the inside lines, and the reason is that the outer rectangle is hugging the exact outside of the SVG. As a result, anything outside of it is cut off. It’s pretty frustrating, but strokes in SVG always straddle the paths that they sit on, so exactly half of the outer stroke (0.5px<\/code>) is hidden. We can double the rectangle alone to “fix” it:<\/p>\n

rect, line {\r\n  fill: none;\r\n  stroke: #000;\r\n  stroke-width: 1px;\r\n  vector-effect: non-scaling-stroke;\r\n}\r\n\r\nrect {\r\n  stroke-width: 2px;\r\n}<\/code><\/pre>\n
\"\"<\/figure>\n

Maxim also tosses a shape-rendering: geometricPrecision;<\/code> on there because, apparently, it cleans things up a bit<\/a> on non-retina displays.<\/p>\n

Step 3: Ants are dashes<\/h3>\n

Other than the weird straddling-the-line thing, SVG strokes offer way more control than CSS borders. For example, CSS has dashed and dotted border styles<\/a>, but offers no control over them. In SVG, we have control over the length of the dashes and the amount of space between them, thanks to stroke-dasharray<\/code><\/a>:<\/p>\n

rect, line {\r\n  ...\r\n\r\n  \/* 8px dashes with 2px spaces *\/\r\n  stroke-dasharray: 8px 2px;\r\n}<\/code><\/pre>\n

We can even get real weird with it:<\/p>\n

\"\"<\/figure>\n

But the ants look good with 4px<\/code> dashes and 4px<\/code> spaces between, so we can use a shorthand of stroke-dasharray: 4px;<\/code>.<\/p>\n

Step 5: Animate the ants!<\/h3>\n

The “marching” part of “marching ants” comes from the animation. SVG strokes also have the ability to be offset by a particular distance. If we pick a distance that is exactly as long as the dash and the gap together, then animate the offset of that distance, we can get a smooth movement of the stroke design. We’ve even covered this before to create an effect of an SVG that draws itself<\/a>.<\/p>\n

rect, line {\r\n  ...\r\n\r\n  stroke-dasharray: 4px;\r\n  stroke-dashoffset: 8px;\r\n  animation: stroke 0.2s linear infinite;\r\n}\r\n\r\n@keyframes stroke {\r\n  to {\r\n    stroke-dashoffset: 0;\r\n  }\r\n}<\/code><\/pre>\n

Here’s our replica<\/a> and the original:<\/p>\n

See the Pen SVG Marching Ants<\/a> by Maxim Leyzerovich (@round<\/a>) on CodePen<\/a>.<\/p>\n

Again, perhaps my favorite part here is the crisp 1px<\/code> lines that aren’t limited by size or aspect ratio at all and how little code it takes to put it all together.<\/p>\n","protected":false},"excerpt":{"rendered":"

Maxim Leyzerovich created the marching ants effect with some delectably simple SVG.<\/p>\n","protected":false},"author":3,"featured_media":277566,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[4],"tags":[1505,966,469],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/10\/marching-ants.gif?fit=800%2C400&ssl=1","jetpack-related-posts":[{"id":301914,"url":"https:\/\/css-tricks.com\/simple-image-placeholders-with-svg\/","url_meta":{"origin":277034,"position":0},"title":"Simple Image Placeholders with SVG","date":"January 27, 2020","format":false,"excerpt":"A little open-source utility from Tyler Sticka\u00a0that returns a data URL of an SVG to use as an image placeholder as needed. I like the idea of self-running utilities like that, rather than depending on some third-party service, like placekitten or whatever. Not that I'd advocate for feature bloat here,\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/01\/Screen-Shot-2020-01-13-at-8.34.41-PM.png?fit=1200%2C675&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":326397,"url":"https:\/\/css-tricks.com\/how-to-animate-a-svg-with-border-image\/","url_meta":{"origin":277034,"position":1},"title":"How to Animate a SVG with border-image","date":"December 3, 2020","format":false,"excerpt":"Let\u2019s take a look at how to combine the border-image property in CSS with animated SVGs that move around a border. In the process, we\u2019ll cover how to hand-craft resizable, nine-slice animated SVGs that you can use not only re-create the effect, but to make it your own. Here\u2019s what\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/11\/animated-skull-border.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":355623,"url":"https:\/\/css-tricks.com\/how-to-create-an-animated-chart-of-nested-squares-using-masks\/","url_meta":{"origin":277034,"position":2},"title":"How to Create an Animated Chart of Nested Squares Using Masks","date":"November 5, 2021","format":false,"excerpt":"We have many well-known chart types: bar, donut, line, pie, you name it. All popular chart libraries support these. Then there are the chart types that do not even have a name. Check out this dreamt-up chart with stacked (nested) squares that can help visualize relative sizes, or how different\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/11\/nested-exploding-square-chart.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":326069,"url":"https:\/\/css-tricks.com\/graphery-svg\/","url_meta":{"origin":277034,"position":3},"title":"Graphery SVG","date":"November 23, 2020","format":false,"excerpt":"I've compared SVG and Canvas before. If you're trying to decide between them, read that. I'd say the #1 difference between them is vector (SVG) versus raster (Canvas). But the #2 difference is how you work with them. SVG is declarative, as in, literal elements that express what they are\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/11\/graphery.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":259249,"url":"https:\/\/css-tricks.com\/saving-svg-space-around-illustrator\/","url_meta":{"origin":277034,"position":4},"title":"Saving SVG with Space Around It from Illustrator","date":"August 18, 2017","format":false,"excerpt":"There are a number of ways to export graphics from Illustrator. Some of them aren't particulary useful (Save As), some of them don't support SVG (Export for Web), some of them produce good output but have limited options that don't allow preserving space around the art (Export As). The only\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":318160,"url":"https:\/\/css-tricks.com\/svg-title-vs-html-title-attribute\/","url_meta":{"origin":277034,"position":5},"title":"SVG Title vs. HTML Title Attribute","date":"July 30, 2020","format":false,"excerpt":"You know the title attribute? I can do this:

I'm a div with a `title` <\/div> And now if I'm on a device with a mouse pointer and hover the cursor over that element, I get... Which, uh, I guess is something. I sometimes use it for\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/07\/title-attribute.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"featured_media_src_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/10\/marching-ants.gif?fit=800%2C400&ssl=1","_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/277034"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=277034"}],"version-history":[{"count":9,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/277034\/revisions"}],"predecessor-version":[{"id":277824,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/277034\/revisions\/277824"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media\/277566"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=277034"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=277034"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=277034"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}