shellsharks.com
Shark Fin <hr>
<p>You may have noticed that I have a <em>bit</em> of a shark theme goin’ on across the site. It’s not <em>overwhelmingly</em> shark-<i>ey</i>, but there’s certainly a shark or two sprinkled abpout - and I think that’s just <strong>fun</strong>. To this end, I had another fun li’l idea. What if I could change the usual boring ‘ol <code class="language-plaintext highlighter-rouge"><hr></code> tag (<a href="https://www.w3schools.com/tags/tag_hr.asp">horizontal rule</a>) and have a shark dorsal fin coming out of it? <em>Sounds cool right?</em> Right.</p><p>I had this <a href="https://shellsharks.com/ideas">idea</a> months or even years ago, I filed it away for another day, thinking it too hard for me to accomplish myself. It would have to be something that I’d need to learn a lot of arcane HTML/CSS to do or maybe I’d just need to hire someone to make it for me. Yesterday, for whatever reason, I decided to try and take it on. I’m going to walk through a bit of my <a href="https://shellsharks.com/devlog/shark-fin-hr#trial-and-error">trial and error</a>, and then get into how I finally <a href="https://shellsharks.com/devlog/shark-fin-hr#shark-fin-hr">pulled it off</a>.</p><h2 id="trial-and-error">Trial and Error</h2><p><em>Let me tell you</em>, getting this to work probably took me 4-5 hours of just sittin’ in my chair, hammering away. Though I can safely say I <em><a href="https://shellsharks.com/devlog/shark-fin-hr#future-improvements">mostly</a></em> figured out everything to get it to work, I also can say I figured out lots of ways it <em>doesn’t</em> work.</p><p>The way I thought this would work originally, and thus the way I approached it at first, was to use HTML’s <a href="https://www.w3schools.com/html/html5_canvas.asp">Canvas Graphics</a> to draw a shark fin <em>and</em> a line, and just use that instead of the normal <code class="language-plaintext highlighter-rouge"><hr></code> tags. Of course I know nothing about drawing with <code class="language-plaintext highlighter-rouge"><canvas></code>, and I absolutely wasn’t going to try and learn it well enough to do it myself, so naturally I googled for an answer. It wasn’t long into this search that I realized maybe drawing with straight CSS would be a better option. So, I searched for that instead. Google came up pretty dry once again, but there was one <em>potential</em> <a href="https://alvaromontoro.com/blog/68021/drawing-a-shark-with-css">splash of luck</a>.<sup id="fnref:1"><a class="footnote" href="https://shellsharks.com/devlog/shark-fin-hr#fn:1" rel="footnote" role="doc-noteref">1</a></sup> Alvaro had managed to draw a (<em>adorably cute</em>) shark entirely with HTML and CSS. <em>Cool!</em> But could I use it somehow? I <em>cmd+C & cmd+V’ed</em> the code and tried ripping out stuff to get to just the fin. I figured if I could isolate the fin, I could tweak it a bit to be what I wanted. I was <em>wrong</em>. I gave up on that after like 10 min.</p><p><em>So now what?</em> I got a bit desperate, from there I tried…</p><ul><li>Searching for web tools that would convert drawings to CSS code</li><li>Searching for vector libraries</li><li>I even used ChatGPT to try and make it (here’s what it came up with - <em>sorry</em> I can’t get the <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox">viewBox</a> to behave)</li></ul><svg fill="none" height="100" viewbox="0 0 100 100" width="100" xmlns="http://www.w3.org/2000/svg"><path d="M50 150 C100 20, 180 80, 160 160 L50 160 Z" fill="#CA3342"></path> </svg><p>Fresh off of humiliating myself by thinking AI could be useful, I came across some <em>actually</em> useful info. Basically, I learned that I could customize <code class="language-plaintext highlighter-rouge"><hr></code> tags with a character, <em>or image</em> using the <code class="language-plaintext highlighter-rouge">::after</code> <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::after">pseudo-element</a>.<sup id="fnref:2"><a class="footnote" href="https://shellsharks.com/devlog/shark-fin-hr#fn:2" rel="footnote" role="doc-noteref">2</a></sup> <em>Neat!</em>. This seemed like a more elegant solution. I could still use <code class="language-plaintext highlighter-rouge"><hr></code> tags, just with a class specifier rather than importing some janky inline-svg + html + css abomination each time I wanted the effect. So, like any seasoned developer, I borrowed the code from the <a href="https://stackoverflow.com/questions/14202089/custom-hr-with-image-character-in-the-center">stack overflow</a> page and started tweaking from there. But then I ran into my next issue, I needed an image to import! And not just any image, I needed something I could move along the <code class="language-plaintext highlighter-rouge"><hr></code> continuum, something I could size up and down, and something I could change the color of. First place I went to was <em><a href="https://en.wikipedia.org/wiki/SVG">.svg</a></em>.</p><p>I spent some time googling around for shark fin <em>.svgs</em> and came across a number of things that would work for me.</p><p><img src="https://shellsharks.com/assets/img/sharkfin.svg"/> <img src="https://shellsharks.com/assets/img/shark-fin-silhouette.svg"/> <img src="https://shellsharks.com/assets/img/shark-fin-notch.svg"/></p><p>The xml syntax within an SVG file is kinda strange, and it took me a while to grok, but eventually I figured out how to change the fill color, resize it to my liking and generate a mirror image so that the shark fin can point both left and right.</p><p><img src="https://shellsharks.com/assets/img/sharkfin-reverse.svg"/> <img src="https://shellsharks.com/assets/img/shark-fin-silhouette-reverse.svg"/> <img src="https://shellsharks.com/assets/img/shark-fin-notch-reverse.svg"/></p><p>So, let me give you the <a href="https://shellsharks.com/devlog/shark-fin-hr#shark-fin-hr">final result</a>…</p><h2 id="shark-fin-hr">Shark Fin <hr></h2><p>Here’s how I finally put together my current v1.0 <b>Shark Fin <hr></b></p><p>Within the SVG, you can resize by changing the ‘width’ property in the <code class="language-plaintext highlighter-rouge"><svg></code> tag. You can change the fill color with the ‘fill’ property in the <code class="language-plaintext highlighter-rouge"><path></code> tag. Finally, for mirroring the image across the Y-axis, you can add <code class="language-plaintext highlighter-rouge">transform="scale (-1, 1)" transform-origin="center"</code> to the <code class="language-plaintext highlighter-rouge"><path></code> tag as well (as shown below). I also had to toy around with the <code class="language-plaintext highlighter-rouge">viewBox</code> to take out unneccessary white-space/padding.</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><svg ... width="35px" viewBox="0 0 1000 1000" ...>
<path fill="#CA3342" transform="scale (-1, 1)" transform-origin="center" ... />
</svg>
</code></pre></div></div><p>My CSS for the ‘fin’ class…</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:root {
--hrfin-position: 40%;
--hrfin-content: url( '/assets/img/shark-fin-notch.svg' );
}
hr.fin {
margin-top: 40px; /* compensating for height of the fin */
margin-bottom: 40px; /* making the bottom margin the same as the top */
border-top: 1px solid var(--accent-color); /% the color that I want the hr tag to be */
border-bottom: 1px solid var(--accent-color);
}
hr.fin:after {
content: var(--hrfin-content); /* Loading the SVG url from :root */
left: var(--hrfin-position); /* Setting the position of the fin along the rule */
position: relative;
bottom:29px; /* Moves the fin closer to the line - it's 6px less than the svg width */
}
</code></pre></div></div><p>So why am I setting the ‘left’ position and loading the svg from <code class="language-plaintext highlighter-rouge">:root</code> instead of directly? Well that’s because I wanted to randomize the fin’s position along the rule on page load. So I have some JavaScript that does this.</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>const root = document.querySelector(":root"); //grabbing the root element
var rand = Math.floor(Math.random() * 90) + 1;
const fins = ["url( '/assets/img/shark-fin-notch.svg' )","url( '/assets/img/shark-fin-notch-reverse.svg' )"]
var fins_rand = Math.round(Math.random());
console.log(fins[fins_rand]);
root.style.setProperty("--hrfin-position", rand + "%");
root.style.setProperty("--hrfin-content", fins[fins_rand]);
</code></pre></div></div><p>So what do I get in the end? <strong>This!</strong></p><hr class="fin"/><p>Try reloading the page a few times and see it change positions and directionality. <em>Niiiiice!</em></p><p>What’s cool too is that even if I shorten the width of the rule, the shark will stay along it.</p><hr class="fin" width="50%"/><h3 id="future-improvements">Future Improvements</h3><p>But things aren’t <em>exactly</em> how I’d like to see them. There are some improvements to be made in future iterations. A wish list of things I’d like to see it do in the future…</p><ol><li>Given the way I am loading the SVG, I can’t dynamically change the color of the fin, it is statically set in the SVG itself. I’m fine with the compromise for now but would like to address this later.</li><li>The fin position (X-axis), set by the CSS ‘left’ directive is the same for all fin-class <em>hrs</em> on the page. Notice how all of them on this page are at the same point on the line. It’d be cool to randomize the position for each instance of the rule on a single page.</li><li>I’m pretty happy with the shark fin SVG I’ve landed on (Thanks <a href="https://www.creativefabrica.com/product/shark-fin-silhouette-svg-shark-fin-svg/">Creative Fabrica</a>!), but could see myself getting something a bit more customized in the future.</li><li>If I wanted to get crazy, maybe I’d have the fins animate in some way, like an actual shark swimmin’ around the rules.</li><li>Another compromise was having to use JavaScript to randomize the svg file and position. Modern/supported versions of CSS don’t have any way to produce a <em>random</em> value. There are some <a href="https://css-tricks.com/random-numbers-css/">hacky ways</a> to achieve this, but I couldn’t figure them out. It’d be cool to have this not be .js-dependent in the future.</li></ol><div class="footnotes" role="doc-endnotes"><ol><li id="fn:1"><p><a href="https://alvaromontoro.com/blog/68021/drawing-a-shark-with-css">Drawing kawaii sharks and sea life with HTML and CSS</a> <a class="reversefootnote" href="https://shellsharks.com/devlog/shark-fin-hr#fnref:1" role="doc-backlink">↩</a></p></li><li id="fn:2"><p><a href="https://stackoverflow.com/questions/14202089/custom-hr-with-image-character-in-the-center">Custom <hr> with image/character in the center | Stack Overflow</a> <a class="reversefootnote" href="https://shellsharks.com/devlog/shark-fin-hr#fnref:2" role="doc-backlink">↩</a></p></li></ol></div>