2026-02-20 11:57:19 -08:00
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
2026-02-19 21:12:12 -08:00
2026-02-20 11:57:19 -08:00
< title > keffiyah fishing net pattern | hello hello< / title >
< meta name = "description" content = "Lee Cattarin... on the internet!" >
< link rel = "alternate" href = "/feed.xml" type = "application/atom+xml" title = "hello hello" >
< meta property = "og:title" content = "keffiyah fishing net pattern" >
< meta property = "og:type" content = "website" >
< meta property = "og:description" content = "Lee Cattarin... on the internet!" >
< meta property = "og:site_name" content = "hello hello" >
< meta property = "og:image" content = "/img/keffiyah-nets.jpg" >
< meta property = "og:image:alt" content = "a knitted swatch. it's mostly white yarn, but a grid of dark red- purple- green yarn that looks like a chain link fence is built into it. the diagonal lines are achieved with floats of yarn from one row, then picked up and knit into several rows later." >
2026-02-19 21:12:12 -08:00
2026-02-20 11:57:19 -08:00
< meta name = "generator" content = "Eleventy v3.1.2" >
2026-02-19 21:12:12 -08:00
2026-02-20 11:57:19 -08:00
< link rel = "preconnect" href = "https://fonts.googleapis.com" >
< link rel = "preconnect" href = "https://fonts.gstatic.com" crossorigin = "" >
< link href = "https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible+Mono:ital,wght@0,200..800;1,200..800&family=Atkinson+Hyperlegible+Next:ital,wght@0,200..800;1,200..800&display=swap" rel = "stylesheet" >
2026-02-19 21:12:12 -08:00
2026-02-20 11:57:19 -08:00
< script src = "https://kit.fontawesome.com/884dded219.js" crossorigin = "anonymous" > < / script >
2026-02-19 21:12:12 -08:00
2026-02-20 11:57:19 -08:00
2026-02-19 21:12:12 -08:00
2026-02-20 11:57:19 -08:00
< style > . p o s t - m e t a d a t a {
2026-02-19 21:12:12 -08:00
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-items: baseline;
margin: 1.5rem 0 .5rem;
}
.post-metadata p {
font-size: .9rem;
margin: 0;
}
.post-tags {
display: flex;
flex-flow: row wrap;
gap: .5rem;
list-style: none;
margin: 0;
}
.post-tags li {
margin: 0;
}
.post-tags li a {
text-decoration: none;
color: var(--color-teal);
padding: 0 .5rem;
border-radius: 1rem;
box-shadow: .15rem .15rem var(--color-shadow);
border: .08rem solid var(--color-teal);
line-height: 2;
/* Click animation handling */
position: relative;
top: 0;
left: 0;
transition: top .1s ease-in, left .1s ease-in;
}
.post-tags li a:focus-visible {
outline: none;
background-color: var(--color-teal);
color: var(--color-bg);
}
@media (any-hover: hover) {
.post-tags li a:hover {
outline: none;
background-color: var(--color-teal);
color: var(--color-bg);
}
}
@media (forced-colors: active) {
.post-tags li a:focus-visible {
outline-offset: .08rem;
outline: .08rem solid;
}
@media (any-hover: hover) {
.post-tags li a:hover {
outline-offset: .08rem;
outline: .08rem solid;
}
}
}
/* Click animation */
.post-tags li a:active {
top: .1rem;
left: .1rem;
box-shadow: .05rem .05rem var(--color-shadow);
}
/* Adapted from PrismJS 1.30.0 Tomorrow Night theme
https://prismjs.com/download
*/
code,
pre,
code[class*=language-],
pre[class*=language-] {
font-family: var(--font-family-code);
background-color: var(--color-bg-alt);
font-size: .9rem;
text-shadow: 0 1px var(--color-shadow);
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre,
pre[class*=language-] {
margin: 1rem 0;
padding: 1rem;
line-height: 1.5;
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: break-word;
border-radius: .5rem;
overflow: auto;
}
:not(pre)>code,
:not(pre)>code[class*=language-] {
padding: .2rem;
border-radius: .25rem;
white-space: normal;
}
/* Selected text */
code ::-moz-selection,
code::-moz-selection,
pre ::-moz-selection,
pre::-moz-selection,
code[class*=language-] ::-moz-selection,
code[class*=language-]::-moz-selection,
pre[class*=language-] ::-moz-selection,
pre[class*=language-]::-moz-selection,
code ::selection,
code::selection,
pre ::selection,
pre::selection,
code[class*=language-] ::selection,
code[class*=language-]::selection,
pre[class*=language-] ::selection,
pre[class*=language-]::selection {
text-shadow: none;
background-color: var(--color-bg);
}
/* Syntax highlighting */
.token.namespace {
opacity: .7;
}
.token.bold,
.token.important {
font-weight:700
}
.token.italic {
font-style:italic
}
.token.block-comment,
.token.cdata,
.token.comment,
.token.doctype,
.token.prolog,
.token.punctuation {
color: var(--color-grey);
}
.token.attr-name,
.token.deleted,
.token.namespace,
.token.tag {
color: var(--color-red);
}
.token.boolean,
.token.function,
.token.number {
color: var(--color-orange);
}
.token.class-name,
.token.constant,
.token.property,
.token.symbol {
color: var(--color-yellow);
}
.token.attr-value,
.token.char,
.token.regex,
.token.string,
.token.variable,
.token.inserted {
color: var(--color-green);
}
.token.entity,
.token.operator,
.token.url,
.token.function-name {
color:var(--color-blue);
}
.token.atrule,
.token.builtin,
.token.important,
.token.keyword,
.token.selector {
color: var(--color-purple);
}
2026-02-20 08:36:56 -08:00
#postlist,
#taglist {
list-style: none;
}
#postlist, .post,
#taglist, .tag {
margin: 0;
}
/* Odd-numbered posts & tag layout/coloration */
.post:nth-child(odd) .postlink,
.tag:nth-child(odd) .taglink {
grid-template-areas:
'img h2'
'img info'
'img .';
grid-template-columns: 45% auto;;
--color-primary: var(--color-teal);
--color-accent: var(--color-pink);
}
/* Even-numbered posts & tags layout/coloration */
.post:nth-child(even) .postlink,
.tag:nth-child(even) .taglink {
grid-template-areas:
'h2 img'
'info img'
'. img';
grid-template-columns: auto 45%;
--color-primary: var(--color-pink);
--color-accent: var(--color-teal);
}
/* Layout for all posts on mobile */
@media (max-width: 650px) {
.post:nth-child(n) .postlink,
.tag:nth-child(n) .taglink {
grid-template-areas:
'img'
'h2'
'info';
grid-template-columns: auto;
}
}
/* Link */
.postlink,
.taglink {
display: grid;
border: .25rem solid var(--color-primary);
border-radius: 1.25rem;
box-shadow: .35rem .35rem var(--color-shadow);
margin: 2rem 0;
text-decoration: none;
/* Click animation handling */
position: relative;
top: 0;
left: 0;
transition: top .05s ease-in, left .05s ease-in;
}
.postlink:focus-visible,
.taglink:focus-visible {
background-color: var(--color-primary);
outline: none;
}
@media (any-hover: hover) {
.postlink:hover,
.taglink:hover {
background-color: var(--color-primary);
}
}
/* Forced colors */
@media (forced-colors: active) {
.postlink:focus-visible,
.taglink:focus-visible {
outline-offset: .25rem;
outline: .25rem solid;
}
@media (any-hover: hover) {
.postlink:hover,
.taglink:hover {
outline-offset: .25rem;
outline: .25rem solid;
}
}
}
/* Click animation */
.postlink:active,
.taglink:active {
box-shadow: none;
top: .2rem;
left: .2rem;
box-shadow: .15rem .15rem var(--color-shadow);
}
/* Post & tag elements */
.post h2, .post img,
.post ul, .post li,
.tag h2, .tag p,
.tag img {
margin: 0;
}
.post h2,
.tag h2 {
grid-area: h2;
padding: .25rem .5rem;
text-transform: uppercase;
font-size: 1.5rem;
color: var(--color-primary);
border-radius: 1rem 1rem 0 0;
border-bottom: .25rem solid var(--color-accent);
}
.post:nth-child(even) h2,
.tag:nth-child(even) h2 {
text-align: right;
}
.postlink:focus-visible h2,
.taglink:focus-visible h2 {
color: var(--color-bg);
border-color: var(--color-bg);
}
@media (any-hover: hover) {
.postlink:hover h2,
.taglink:hover h2 {
color: var(--color-bg);
border-color: var(--color-bg);
}
}
/* Images */
.post img,
.tag-imgs {
grid-area: img;
}
.tag-imgs {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: .15rem;
}
.tag-imgs img {
aspect-ratio: 3 / 2;
object-fit: cover;
}
.missing-image {
width: 100%;
aspect-ratio: 3 / 2;
background-color: var(--color-bg-alt);
border-radius: calc(1rem);
}
.taglink:focus-visible .missing-image {
opacity: .7;
}
@media (any-hover: hover) {
.taglink:hover .missing-image {
opacity: .7;
}
}
/* Post tags */
.postlist-tags {
grid-area: info;
list-style: none;
display: flex;
flex-flow: row wrap;
gap: .5rem;
padding: .5rem;
}
.post:nth-child(odd) .postlist-tags {
justify-content: flex-end;
}
.postlist-tags li,
.tagcount {
background-color: var(--color-primary);
color: var(--color-bg);
padding: 0 .5rem;
border-radius: 1rem;
}
.postlink:focus-visible .postlist-tags li,
.taglink:focus-visible .tagcount {
background-color: var(--color-bg);
color: var(--color-primary);
}
@media (any-hover: hover) {
.postlink:hover .postlist-tags li,
.taglink:hover .tagcount {
background-color: var(--color-bg);
color: var(--color-primary);
}
}
/* Tag count */
.tag p {
grid-area: info;
padding: .5rem;
}
.tag:nth-child(odd) p {
text-align: right;
}
2026-02-19 21:12:12 -08:00
:root {
color-scheme: light dark;
--font-family: 'Atkinson Hyperlegible Next', sans-serif;
--font-family-code: 'Atkinson Hyperlegible Mono', monospace;
--color-dark: #2e303e;
--color-dark-alt: #3c3f52;
--color-light: #ebeeef;
--color-light-alt: #dbe1e3;
--color-teal-dark: #18737b;
--color-teal-light: #25b0bc;
--color-pink-dark: #94195d;
--color-pink-light: #ee9fcb;
--color-shadow: rgba(2, 10, 40, .25);
/* Used for syntax highlighting */
--color-red-light: #e95678;
--color-orange-light: #fab795;
--color-yellow-light: #fbe6bc;
--color-green-light: #29d398;
--color-blue-light: #26bbd9;
--color-purple-light: #ddaeea;
--color-grey-light: #b9c3c6;
--color-red-dark: #991433;
--color-orange-dark: #883206;
--color-yellow-dark: #6a4906;
--color-green-dark: #125940;
--color-blue-dark: #125663;
--color-purple-dark: #722999;
--color-grey-dark: #4a4b64;
--color-text: light-dark(var(--color-dark), var(--color-light));
--color-bg: light-dark(var(--color-light), var(--color-dark));
--color-text-alt: light-dark(var(--color-dark-alt), var(--color-light-alt));
--color-bg-alt: light-dark(var(--color-light-alt), var(--color-dark-alt));
--color-teal: light-dark(var(--color-teal-dark), var(--color-teal-light));
--color-pink: light-dark(var(--color-pink-dark), var(--color-pink-light));
--color-red: light-dark(var(--color-red-dark), var(--color-red-light));
--color-orange: light-dark(var(--color-orange-dark), var(--color-orange-light));
--color-yellow: light-dark(var(--color-yellow-dark), var(--color-yellow-light));
--color-green: light-dark(var(--color-green-dark), var(--color-green-light));
--color-blue: light-dark(var(--color-blue-dark), var(--color-blue-light));
--color-purple: light-dark(var(--color-purple-dark), var(--color-purple-light));
--color-grey: light-dark(var(--color-grey-dark), var(--color-grey-light));
}
/* Base */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: var(--font-family);
color: var(--color-text);
background-color: var(--color-bg);
}
main {
width: 60vw;
max-width: 1000px;
margin: 0 auto;
2026-02-20 08:36:56 -08:00
scroll-margin-top: 7rem;
2026-02-19 21:12:12 -08:00
}
@media (max-width: 1050px) {
main {
width: 75vw;
}
}
@media (max-width: 650px) {
main {
width: 92vw;
}
}
/* Headers */
h1, h2, h3, h4, h5, h6 {
line-height: 1.25;
color: var(--color-teal);
}
h1 {
margin-top: 3rem;
font-size: 3.5rem;
text-align: center;
}
2026-02-20 08:36:56 -08:00
h2, h3, h4, h5, h6 {
scroll-margin-top: 5rem;
}
2026-02-19 21:12:12 -08:00
h2 {
margin-top: 2rem;
font-size: 2.2rem;
}
h3 {
margin-top: 1.5rem;
font-size: 1.6rem;
}
@media (max-width: 650px) {
h1 { font-size: 2.8rem; }
h2 { font-size: 1.8rem; }
h3 { font-size: 1.35rem; }
}
h4, h5, h6 {
margin-top: 1rem;
font-size: 1.2rem;
}
/* Images */
img {
display: block;
max-width: 100%;
height: auto;
border-radius: 1rem;
}
/* Paragraphs */
p {
margin: 1.25rem 0;
line-height: 1.4;
}
strong,
b {
font-weight: 900;
}
/* Links */
a {
color: var(--color-text);
border-radius: .25rem;
text-decoration: underline;
text-decoration-style: solid;
text-decoration-thickness: .2em;
text-decoration-color: var(--color-teal);
transition: text-decoration-thickness .5s;
}
a:focus-visible {
text-decoration: none;
outline: .15rem solid var(--color-teal);
}
@media (any-hover: hover) {
a:hover {
text-decoration-thickness: .4em;
}
}
a:active {
text-decoration-thickness: .4em;
}
/* Heading anchors */
a.ha,
span.ha-placeholder {
color: var(--color-pink);
}
span.ha-placeholder {
2026-02-20 11:57:19 -08:00
opacity: .8;
2026-02-19 21:12:12 -08:00
}
/* Lists */
::marker {
color: var(--color-pink);
}
ul, ol, dl, li {
margin-left: 1rem;
}
li {
line-height: 1.2 5;
margin-top: .65rem;
margin-bottom: .65rem;
}
li ul, li ol {
margin: .5rem 0;
}
dt {
font-weight: 900;
margin-top: .5rem;
}
dd {
margin-left: 2rem;
margin-bottom: .75rem;
}
/* Blockquotes */
blockquote {
margin: .5rem 0;
padding: 0 1rem;
border-radius: .25rem 1rem 1rem .25rem;
line-height: 1.25;
border-left: .5rem solid var(--color-pink);
}
blockquote,
blockquote p,
blockquote ol,
blockquote ul {
background-color: var(--color-bg-alt);
padding: .5rem;
}
blockquote p {
margin: 0;
}
/* Tables */
table {
width: 100%;
border-spacing: 0; /* border collapse doesn't play nice with radii */
border-radius: .3rem;
border: thin solid var(--color-pink);
}
th {
color: var(--color-bg);
background-color: var(--color-pink);
}
th code {
color: var(--color-text); /* Yes, I actually do this somewhere */
}
th, td {
padding: .5rem;
text-align: left;
}
tr:nth-child(even) { background-color: var(--color-bg-alt); }
th:not(:first-child) { border-left: thin solid var(--color-bg); }
th:first-child { border-top-left-radius: .25rem; }
th:last-child { border-top-right-radius: .25rem; }
td:not(:first-child) { border-left: thin solid var(--color-pink); }
/* Times */
time {
color: var(--color-grey);
}
/* Horizontal rules */
hr {
2026-02-20 08:36:56 -08:00
border: .25rem solid var(--color-pink);
2026-02-19 21:12:12 -08:00
margin: 2rem 0;
}
/* Used on home, reference, gallery pages */
.centered {
text-align: center;
}
/* Currently only used for resume, but it's generalizable */
.upper {
text-transform: uppercase;
}
/* Header */
header {
position: sticky;
top: 0;
background-color: var(--color-bg);
padding: .75rem 0;
z-index: 10;
2026-02-20 08:46:50 -08:00
border-bottom: thick solid var(--color-teal);
2026-02-20 08:36:56 -08:00
box-shadow: 0 .25rem .15rem var(--color-shadow);
2026-02-19 21:12:12 -08:00
}
/* Header links, pagination links */
header a,
.pagination a,
.webring ul a {
border-radius: 1rem;
border: .125rem solid var(--color-pink);
color: var(--color-pink);
text-decoration: none;
padding: 0 .25rem;
box-shadow: .15rem .15rem var(--color-shadow);
font-size: 1.2rem;
/* Click animation handling */
position: relative;
top: 0;
left: 0;
transition: top .05s ease-in, left .05s ease-in;
}
header a,
.pagination .older a,
.webring .prev a,
.webring .rand a {
padding-right: .35rem;
}
.pagination .newer a,
.webring .next a,
.webring .rand a {
padding-left: .35rem;
}
header a:focus-visible,
.pagination a:focus-visible,
.webring ul a:focus-visible {
color: var(--color-bg);
border-color: var(--color-pink);
background-color: var(--color-pink);
outline: none;
}
@media (any-hover: hover) {
header a:hover,
.pagination a:hover,
.webring ul a:hover {
color: var(--color-bg);
border-color: var(--color-pink);
background-color: var(--color-pink);
}
}
@media (forced-colors: active) {
header a:focus-visible,
.pagination a:focus-visible,
.webring ul a:focus-visible {
outline-offset: .125rem;
outline: .125rem solid;
}
@media (any-hover: hover) {
header a:hover,
.pagination a:hover,
.webring ul a:hover {
outline-offset: .125rem;
outline: .125rem solid;
}
}
}
/* Click animation */
header a:active,
.pagination a:active,
.webring ul a:active {
top: .1rem;
left: .1rem;
box-shadow: .05rem .05rem var(--color-shadow);
}
/* Current page */
header a[aria-current="page"] {
border-color: var(--color-teal);
color: var(--color-teal);
}
header a[aria-current="page"]:focus-visible {
color: var(--color-bg);
border-color: var(--color-teal);
background-color: var(--color-teal);
}
@media (any-hover: hover) {
header a[aria-current="page"]:hover {
color: var(--color-bg);
background-color: var(--color-teal);
border-color: var(--color-teal);
}
}
/* Header link icons, pagination icons */
header i,
.pagination i,
.webring ul i {
color: var(--color-teal);
}
header i,
.pagination .older i,
.webring .prev i,
.webring .rand i:nth-child(1) {
padding-left: .25rem;
}
.pagination .newer i,
.webring .next i,
.webring .rand i:nth-child(2) {
padding-right: .25rem;
}
header a[aria-current="page"] i {
color: var(--color-pink);
}
header a:focus-visible i,
a[aria-current="page"] a:focus-visible i,
.pagination a:focus-visible i,
.webring ul a:focus-visible i {
color: var(--color-bg);
}
@media (any-hover: hover) {
header a:hover i,
header a[aria-current="page"]:hover i,
.pagination a:hover i,
.webring ul a:hover i {
color: var(--color-bg);
}
}
/* Skip link */
#skip {
left: -999px;
position: absolute;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
z-index: -99;
}
#skip:focus-visible {
display: inline-block;
left: auto;
top: auto;
width: auto;
height: auto;
overflow: auto;
margin: 0 10%;
z-index: 999;
}
/* Nav */
header ul {
display: flex;
list-style: none;
gap: 1rem;
justify-content: center;
}
header ul,
header li {
margin: 0;
}
@media (max-width: 650px) {
.menu-text {
display: none; /* Icons only on small screens */
}
header a {
padding: .15rem .5rem;
}
header i {
padding: 0;
}
}
/* Footer */
footer {
padding: 1rem 0;
font-size: .9rem;
2026-02-20 08:46:50 -08:00
border-top: thick solid var(--color-pink);
2026-02-19 21:12:12 -08:00
}
footer ul {
display: flex;
list-style: none;
gap: .5rem;
justify-content: center;
margin: 0;
}
footer li {
margin: 0;
}
footer li:nth-child(2)::before,
footer li:nth-child(2)::after {
content: " ● " / "";
color: var(--color-teal);
}
@media (max-width: 650px) {
footer ul {
flex-flow: column;
text-align: center;
}
footer li:nth-child(2)::before,
footer li:nth-child(2)::after {
content: none;
}
}
footer a {
text-decoration-color: var(--color-pink);
}
footer a:focus-visible {
outline-color: var(--color-pink);
}
/* Pagination */
.pagination,
.pagination li {
margin: 0;
}
.pagination {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-areas: "older newer";
list-style: none;
margin-top: 3rem;
}
@media (max-width: 650px) {
.post-pagination {
grid-template-columns: 1fr;
grid-template-areas:
"older"
"newer";
gap: .75rem;
}
}
.pagination .older {
grid-area: older;
}
.pagination .newer {
grid-area: newer;
text-align: right;
}
/* webring navigation */
.webring {
margin-bottom: 3rem;
}
.webring ul {
display: flex;
flex-flow: row wrap;
list-style: none;
justify-content: space-around;
gap: .35rem;
}
.webring ul,
.webring li {
margin-left: 0;
}
@media print {
/* Nav elements */
header,
footer,
nav {
display: none !important;
}
/* Base */
body {
background-color: #fff;
color: #000;
}
main {
width: 95vw;
}
h1,h2,h3,h4,h5,h6 {
color: #000;
}
/* Links */
/* Hover is not really necessary, but it's annoying when testing otherwise */
a,
a:hover {
text-decoration-style: dotted;
text-decoration-thickness: .1rem;
text-decoration-color: #000;
}
a::after{
content: " (" attr(href) ")";
}
/* Code */
code,
pre,
code[class*=language-],
pre[class*=language-] {
text-shadow: none;
background-color: var(--color-light);
color: #000 !important;
}
.token.namespace {
opacity: 1;
}
.token.block-comment,
.token.cdata,
.token.comment,
.token.doctype,
.token.prolog,
.token.punctuation,
.token.attr-name,
.token.deleted,
.token.namespace,
.token.tag,
.token.boolean,
.token.function,
.token.number,
.token.class-name,
.token.constant,
.token.property,
.token.symbol,
.token.attr-value,
.token.char,
.token.regex,
.token.string,
.token.variable,
.token.inserted,
.token.entity,
.token.operator,
.token.url,
.token.function-name,
.token.atrule,
.token.builtin,
.token.important,
.token.keyword,
.token.selector {
color: #000;
}
}< / style >
2026-02-20 11:57:19 -08:00
< script type = "module" > / / T h a n k y o u t o h t t p s : / / g i t h u b . c o m / d a v i d d a r n e s / h e a d i n g - a n c h o r s
2026-02-19 21:12:12 -08:00
// Thank you to https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/
let globalInstanceIndex = 0;
class HeadingAnchors extends HTMLElement {
static register(tagName = "heading-anchors", registry = window.customElements) {
if(registry & & !registry.get(tagName)) {
registry.define(tagName, this);
}
}
static attributes = {
exclude: "data-ha-exclude",
prefix: "prefix",
content: "content",
}
static classes = {
anchor: "ha",
placeholder: "ha-placeholder",
srOnly: "ha-visualhide",
}
static defaultSelector = "h2,h3,h4,h5,h6";
static css = `
.${HeadingAnchors.classes.srOnly} {
clip: rect(0 0 0 0);
height: 1px;
overflow: hidden;
position: absolute;
width: 1px;
}
.${HeadingAnchors.classes.anchor} {
position: absolute;
left: var(--ha_offsetx);
top: var(--ha_offsety);
text-decoration: none;
opacity: 0;
}
.${HeadingAnchors.classes.placeholder} {
opacity: .3;
}
.${HeadingAnchors.classes.anchor}:is(:focus-within, :hover) {
opacity: 1;
}
.${HeadingAnchors.classes.anchor},
.${HeadingAnchors.classes.placeholder} {
display: inline-block;
padding: 0 .25em;
/* Disable selection of visually hidden label */
-webkit-user-select: none;
user-select: none;
}
@supports (anchor-name: none) {
.${HeadingAnchors.classes.anchor} {
position: absolute;
left: anchor(left);
top: anchor(top);
}
}`;
get supports() {
return "replaceSync" in CSSStyleSheet.prototype;
}
get supportsAnchorPosition() {
return CSS.supports("anchor-name: none");
}
constructor() {
super();
if(!this.supports) {
return;
}
let sheet = new CSSStyleSheet();
sheet.replaceSync(HeadingAnchors.css);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
this.headingStyles = {};
this.instanceIndex = globalInstanceIndex++;
}
connectedCallback() {
if (!this.supports) {
return;
}
this.headings.forEach((heading, index) => {
if(!heading.hasAttribute(HeadingAnchors.attributes.exclude)) {
let anchor = this.getAnchorElement(heading);
let placeholder = this.getPlaceholderElement();
// Prefers anchor position approach for better accessibility
// https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/
if(this.supportsAnchorPosition) {
let anchorName = `--ha_${this.instanceIndex}_${index}`;
placeholder.style.setProperty("anchor-name", anchorName);
anchor.style.positionAnchor = anchorName;
}
heading.appendChild(placeholder);
heading.after(anchor);
}
});
}
// Polyfill-only
positionAnchorFromPlaceholder(placeholder) {
if(!placeholder) {
return;
}
let heading = placeholder.closest("h1,h2,h3,h4,h5,h6");
if(!heading.nextElementSibling) {
return;
}
// TODO next element could be more defensive
this.positionAnchor(heading.nextElementSibling);
}
// Polyfill-only
positionAnchor(anchor) {
if(!anchor || !anchor.previousElementSibling) {
return;
}
// TODO previous element could be more defensive
let heading = anchor.previousElementSibling;
this.setFontProp(heading, anchor);
if(this.supportsAnchorPosition) {
// quit early
return;
}
let placeholder = heading.querySelector(`.${HeadingAnchors.classes.placeholder}`);
if(placeholder) {
anchor.style.setProperty("--ha_offsetx", `${placeholder.offsetLeft}px`);
anchor.style.setProperty("--ha_offsety", `${placeholder.offsetTop}px`);
}
}
setFontProp(heading, anchor) {
let placeholder = heading.querySelector(`.${HeadingAnchors.classes.placeholder}`);
if(placeholder) {
let style = getComputedStyle(placeholder);
let props = ["font-weight", "font-size", "line-height", "font-family"];
let [weight, size, lh, family] = props.map(name => style.getPropertyValue(name));
anchor.style.setProperty("font", `${weight} ${size}/${lh} ${family}`);
let vars = style.getPropertyValue("font-variation-settings");
if(vars) {
anchor.style.setProperty("font-variation-settings", vars);
}
}
}
getAccessibleTextPrefix() {
// Useful for i18n
return this.getAttribute(HeadingAnchors.attributes.prefix) || "Jump to section titled";
}
getContent() {
if(this.hasAttribute(HeadingAnchors.attributes.content)) {
return this.getAttribute(HeadingAnchors.attributes.content);
}
return "#";
}
// Placeholder nests inside of heading
getPlaceholderElement() {
let ph = document.createElement("span");
ph.setAttribute("aria-hidden", true);
ph.classList.add(HeadingAnchors.classes.placeholder);
let content = this.getContent();
if(content) {
ph.innerHTML = content; // CHANGED HERE
}
ph.addEventListener("mouseover", (e) => {
let placeholder = e.target.closest(`.${HeadingAnchors.classes.placeholder}`);
if(placeholder) {
this.positionAnchorFromPlaceholder(placeholder);
}
});
return ph;
}
getAnchorElement(heading) {
let anchor = document.createElement("a");
anchor.href = `#${heading.id}`;
anchor.classList.add(HeadingAnchors.classes.anchor);
let content = this.getContent();
anchor.innerHTML = `< span class = "${HeadingAnchors.classes.srOnly}" > ${this.getAccessibleTextPrefix()}: ${heading.textContent}< / span > ${content ? `< span aria-hidden = "true" > ${content}< / span > ` : ""}`;
anchor.addEventListener("focus", e => {
let anchor = e.target.closest(`.${HeadingAnchors.classes.anchor}`);
if(anchor) {
this.positionAnchor(anchor);
}
});
anchor.addEventListener("mouseover", (e) => {
// when CSS anchor positioning is supported, this is only used to set the font
let anchor = e.target.closest(`.${HeadingAnchors.classes.anchor}`);
this.positionAnchor(anchor);
});
return anchor;
}
get headings() {
return this.querySelectorAll(this.selector.split(",").map(entry => `${entry.trim()}[id]`));
}
get selector() {
return this.getAttribute("selector") || HeadingAnchors.defaultSelector;
}
}
HeadingAnchors.register();
export { HeadingAnchors }< / script >
2026-02-20 11:57:19 -08:00
< / head >
< body >
< header >
2026-02-19 21:12:12 -08:00
< a href = "#main" id = "skip" title = "skip to main content" aria-label = "skip to main content" >
< i class = "fa-solid fa-forward" aria-hidden = "true" > < / i > skip
< / a >
< nav aria-label = "main navigation" >
< ul >
< li >
2026-02-20 11:57:19 -08:00
< a href = "/reference/" title = "read reference posts" >
2026-02-19 21:12:12 -08:00
< i class = "fa-regular fa-folder-open" aria-hidden = "true" > < / i >
< span class = "menu-text" > reference< / span >
< / a >
< / li >
< li >
2026-02-20 11:57:19 -08:00
< a href = "/gallery/" title = "view the gallery" >
2026-02-19 21:12:12 -08:00
< i class = "fa-regular fa-images" aria-hidden = "true" > < / i >
< span class = "menu-text" > gallery< / span >
< / a >
< / li >
< li >
2026-02-20 11:57:19 -08:00
< a href = "/" title = "" >
2026-02-19 21:12:12 -08:00
< i class = "fa fa-solid fa-crow" aria-hidden = "true" > < / i >
< span class = "menu-text" > home< / span >
< / a >
< / li >
< li >
2026-02-20 11:57:19 -08:00
< a href = "/about/" title = "about Lee" >
2026-02-19 21:12:12 -08:00
< i class = "fa-regular fa-user" aria-hidden = "true" > < / i >
< span class = "menu-text" > about< / span >
< / a >
< / li >
< li >
2026-02-20 11:57:19 -08:00
< a href = "/contact/" title = "contact Lee" >
2026-02-19 21:12:12 -08:00
< i class = "fa-solid fa-envelope-open-text" aria-hidden = "true" > < / i >
< span class = "menu-text" > contact< / span >
< / a >
< / li >
< / ul >
< / nav >
< / header >
2026-02-20 11:57:19 -08:00
< main id = "main" >
2026-02-19 21:12:12 -08:00
2026-02-20 08:36:56 -08:00
2026-02-19 21:12:12 -08:00
< heading-anchors content = "<i class='fa-solid fa-anchor'></i>" >
< article >
< h1 id = "keffiyah-fishing-net-pattern" > keffiyah fishing net pattern< / h1 >
< div class = "post-metadata" >
< p >
posted on
< time datetime = "2025-05-26" > May 26, 2025< / time >
by Lee Cattarin
< / p >
< ul class = "post-tags" >
< li >
< a href = "/tags/knit/" > knit< / a >
< / li >
< / ul >
< / div >
< img src = "/img/keffiyah-nets.jpg" alt = "a knitted swatch. it's mostly white yarn, but a grid of dark red- purple- green yarn that looks like a chain link fence is built into it. the diagonal lines are achieved with floats of yarn from one row, then picked up and knit into several rows later." loading = "lazy" decoding = "async" width = "1000" height = "750" >
< h2 id = "give" > give< / h2 >
< p > this pattern is offered at no cost, but I highly encourage giving to Palestinian relief work.< / p >
< ul >
< li > < a href = "https://www.pcrf.net" target = "_blank" rel = "external" > Palestine Children's Relief Fund< / a > < / li >
< / ul >
< h2 id = "abbreviations" > abbreviations< / h2 >
< table >
< thead >
< tr >
< th > abbr< / th >
< th > term< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > < strong > MC< / strong > < / td >
< td > main color (light in swatch shown)< / td >
< / tr >
< tr >
< td > < strong > CC< / strong > < / td >
< td > contrast color (dark in swatch shown)< / td >
< / tr >
< tr >
< td > < strong > RS< / strong > < / td >
< td > right side< / td >
< / tr >
< tr >
< td > < strong > WS< / strong > < / td >
< td > wrong side< / td >
< / tr >
< tr >
< td > < strong > k< / strong > < / td >
< td > knit< / td >
< / tr >
< tr >
< td > < strong > sl< / strong > < / td >
< td > slip< / td >
< / tr >
< tr >
< td > < strong > wyif< / strong > < / td >
< td > with yarn in front< / td >
< / tr >
< tr >
< td > < strong > p< / strong > < / td >
< td > purl< / td >
< / tr >
< / tbody >
< / table >
< h2 id = "techniques" > techniques< / h2 >
< h3 id = "knit-into-a-float" > knit into a float< / h3 >
< p > in this pattern, you will be creating floats on the front of the work, then picking them up and knitting into them 3 rows later. < strong > Do this as part of the stitch you are working, not instead of!< / strong > You should have the same number of stitches afterwards.< / p >
< p > when you pick up a float, you want it to sit < strong > in front of the worked stitch, and untwisted.< / strong > To achieve this, I have been catching the float on my right needle by dipping the needle down and under the float, from the front to the back. From there, I work the stitch, then slip the float over the new stitch on my right needle.< / p >
< h2 id = "knit-flat" > knit flat< / h2 >
< h3 id = "cast-on" > cast on< / h3 >
< p > knit flat, the pattern repeat uses 6n + 1 stitches. In the swatch shown, I cast on 29 stitches - 2 on each side for selvedge, then 25 -- 6 * 4 + 1. To simplify things, I'll write the pattern for the swatch, selvedge and all - but please adapt as you see fit.< / p >
< p > with MC, cast on 29 stitches.< / p >
< h3 id = "establish-the-pattern" > establish the pattern< / h3 >
< ul >
< li > < strong > row 0 (WS):< / strong > with MC, knit to last stitch, sl1 wyif< / li >
< li > < strong > row 1 (RS):< / strong >
< ul >
< li > with MC, k2< / li >
< li > [with CC, k1; with MC, k5] * 4, then with CC, k1< / li >
< li > with MC, k1, sl1 wyif< / li >
< / ul >
< / li >
< li > < strong > row 2 (WS):< / strong >
< ul >
< li > with MC, k1, p1< / li >
< li > [with CC, k1 and leave working yarn on RS; with MC, p5] * 4, then with CC, k1 and bring working yarn back to WS< / li >
< li > with MC, p1, sl1 wyif< / li >
< / ul >
< / li >
< / ul >
< h3 id = "pattern-repeat" > pattern repeat< / h3 >
< ul >
< li > < strong > row 3 (RS):< / strong > with MC, knit to last stitch, sl1 wyif< / li >
< li > < strong > row 4 (WS):< / strong > with MC, k1, purl to last stitch, sl1 wyif< / li >
< li > < strong > row 5 (RS):< / strong >
< ul >
< li > with MC, k5< / li >
< li > [with CC, k1 into the float from 3 rows below; with MC, k5] * 4< / li >
< li > with MC, k4, sl1 wyif< / li >
< / ul >
< / li >
< li > < strong > row 6 (RS):< / strong >
< ul >
< li > with MC, k1, p4< / li >
< li > [with CC, k1 and leave working yarn on RS; with MC, p5] * 4 -- on the last repeat, move working yarn back to WS before purling< / li >
< li > with MC, p4, sl1 wyif< / li >
< / ul >
< / li >
< li > < strong > rows 7-8:< / strong > repeat rows 3-4< / li >
< li > < strong > row 9 (RS):< / strong >
< ul >
< li > with MC, k2< / li >
< li > [with CC, k1 into the float from 3 rows below; with MC, k5] * 4, then with CC, k1< / li >
< li > with MC, k1, sl1 wyif< / li >
< / ul >
< / li >
< li > < strong > row 10 (WS):< / strong >
< ul >
< li > with MC, k1, p1< / li >
< li > [with CC, k1 and leave working yarn on RS; with MC, p5] * 4, then with CC, k1 and bring working yarn back to WS< / li >
< li > with MC, p1, sl1 wyif< / li >
< / ul >
< / li >
< / ul >
< h3 id = "close-the-pattern" > close the pattern< / h3 >
< p > end after rows 5 or 9 of the pattern repeat. replace row 6 or 10 with the following:< / p >
< ul >
< li > < strong > row 6 alteration:< / strong >
< ul >
< li > with MC, k1, p4< / li >
< li > [with CC, k1; with MC, p5] * 4< / li >
< li > with MC, p4, sl1 wyif< / li >
< / ul >
< / li >
< li > < strong > row 10 alteration:< / strong >
< ul >
< li > with MC, k1, p1< / li >
< li > [with CC, k1; with MC, p5] * 4, then with CC, k1< / li >
< li > with MC, p1, sl1 wyif< / li >
< / ul >
< / li >
< / ul >
< p > to end my swatch, I did the following:< / p >
< ul >
< li > < strong > row (RS):< / strong > with MC, knit to last stitch, sl1 wyif< / li >
< li > < strong > row (WS):< / strong > with MC, k1, purl to last stitch, sl1 wyif< / li >
< li > < strong > row (RS):< / strong > with MC, bind off< / li >
< / ul >
< h2 id = "knit-in-the-round" > knit in the round< / h2 >
< h3 id = "cast-on-2" > cast on< / h3 >
< p > with MC, cast on a multiple of 6 stitches. knit in plain stockinette until you are ready to start the pattern.< / p >
< h3 id = "establish-the-pattern-2" > establish the pattern< / h3 >
< ul >
< li > < strong > row 1:< / strong >
< ul >
< li > [with CC, k1; with MC, k5] repeat to last 6 stitches< / li >
< li > with CC, k1 and leave working yarn on RS; with MC, k5< / li >
< / ul >
< / li >
< li > < strong > row 2:< / strong >
< ul >
< li > [with CC, p1 and leave working yarn on RS; with MC, k5] repeat to last 6 stitches< / li >
< li > with CC, p1 and move working yarn to WS; with MC, k5< / li >
< / ul >
< / li >
< / ul >
< h3 id = "pattern-repeat-2" > pattern repeat< / h3 >
< ul >
< li > < strong > rows 3-4:< / strong > with MC, knit all stitches< / li >
< li > < strong > row 5:< / strong >
< ul >
< li > with MC, k3< / li >
< li > [with CC, k1 into the float from 3 rows below; with MC, k5] repeat to last 3 stitches< / li >
< li > with CC, k1 and leave working yarn on RS; with MC, k2< / li >
< / ul >
< / li >
< li > < strong > row 6:< / strong >
< ul >
< li > with MC, k3< / li >
< li > [with CC, p1 and leave working yarn on RS; with MC, k5] repeat to last 3 stitches< / li >
< li > with CC, p1 and moving working yarn to WS; with MC, k2< / li >
< / ul >
< / li >
< li > < strong > rows 7-8:< / strong > repeat rows 3-4< / li >
< li > < strong > row 9:< / strong >
< ul >
< li > [with CC, k1 into the float from 3 rows below; with MC, k5] repeat to last 6 stitches< / li >
< li > with CC, k1 into the float from 3 rows below and leave working yarn on RS; with MC, k5< / li >
< / ul >
< / li >
< li > < strong > rows 10:< / strong >
< ul >
< li > [with CC, p1 and leave working yarn on RS; with MC, k5] repeat to last 6 stitches< / li >
< li > with CC, p1 and move working yarn to WS; with MC, k5< / li >
< / ul >
< / li >
< / ul >
< h3 id = "close-the-pattern-2" > close the pattern< / h3 >
< p > end after rows 5 or 9 of the pattern repeat. replace row 6 or 10 with the following:< / p >
< ul >
< li > < strong > row 6 alteration:< / strong >
< ul >
< li > with MC, k3< / li >
< li > [with CC, p1; with MC, k5] repeat to last 3 stitches< / li >
< li > with CC, p1; with MC, k2< / li >
< / ul >
< / li >
< li > < strong > row 10 alteration:< / strong > [with CC, p1; with MC, k5] repeat for all stitches< / li >
< / ul >
< p > with MC, knit in plain stockinette until you want to bind off, then bind off.< / p >
< / article >
< nav aria-label = "pagination" >
< ol class = "pagination post-pagination" >
< li class = "older" >
< a href = "/art-shows-and-events/" >
< i class = "fa-solid fa-hand-point-left" aria-hidden = "true" > < / i > art shows and events
< / a >
< / li >
< li class = "newer" >
< a href = "/scrap-patches/" >
scrap patches < i class = "fa-solid fa-hand-point-right" aria-hidden = "true" > < / i >
< / a >
< / li >
< / ol >
< / nav >
2026-02-20 08:36:56 -08:00
< hr >
< section class = "related-posts" >
< h2 id = "related-posts" > related posts< / h2 >
< ol id = "postlist" >
< li class = "post" >
2026-02-20 11:57:19 -08:00
< a class = "postlink" href = "/brookes-scarf/" >
2026-02-20 08:36:56 -08:00
2026-02-20 11:57:19 -08:00
< img src = "/img/brooke-scarf.jpg" alt = "A diaphanous knit lacework scarf draped over the back of a chair. It is split down the long way into two colors - one tinted orange and one tinted mint blue. Both colors, the orange and the blue, are held double with the same variegated gray, making the piece more cohesive. The yarn overs in the lacework create airy repeating holes." loading = "lazy" decoding = "async" width = "1000" height = "1333" >
2026-02-20 08:36:56 -08:00
2026-02-20 11:57:19 -08:00
< h2 id = "brookes-scarf" > brooke' s scarf< / h2 >
2026-02-20 08:36:56 -08:00
< ul class = "postlist-tags" >
< li > knit< / li >
< / ul >
< / a >
< / li >
< li class = "post" >
2026-02-20 11:57:19 -08:00
< a class = "postlink" href = "/pride-dice-bags/" >
2026-02-20 08:36:56 -08:00
2026-02-20 11:57:19 -08:00
< img src = "/img/pride-dice-bags.jpg" alt = "Several knitted drawstring dice bags sit in front of a bookshelf. They are in different pride flag colors; from right to left (skipping a few duplicates) bisexual, lesbian, nonbinary, trans, and genderqueer. The trans-colored dice bag in the center opens towards the camera, showing a variety of colorful dice inside." loading = "lazy" decoding = "async" width = "1000" height = "500" >
2026-02-20 08:36:56 -08:00
2026-02-20 11:57:19 -08:00
< h2 id = "pride-dice-bags" > pride dice bags< / h2 >
2026-02-20 08:36:56 -08:00
< ul class = "postlist-tags" >
< li > knit< / li >
2026-02-20 11:57:19 -08:00
< li > gender< / li >
2026-02-20 08:36:56 -08:00
< / ul >
< / a >
< / li >
< li class = "post" >
2026-02-20 11:57:19 -08:00
< a class = "postlink" href = "/brookes-socks/" >
2026-02-20 08:36:56 -08:00
2026-02-20 11:57:19 -08:00
< img src = "/img/brooke-socks.jpg" alt = "Feet in a pair of colorful socks. They are identically striped and quickly vary between yellow, green, blue, white, and gray." loading = "lazy" decoding = "async" width = "1000" height = "750" >
2026-02-20 08:36:56 -08:00
2026-02-20 11:57:19 -08:00
< h2 id = "brookes-socks" > brooke' s socks< / h2 >
2026-02-20 08:36:56 -08:00
< ul class = "postlist-tags" >
< li > knit< / li >
< / ul >
< / a >
< / li >
< / ol >
< / section >
< / heading-anchors >
2026-02-19 21:12:12 -08:00
2026-02-20 11:57:19 -08:00
< / main >
2026-02-19 21:12:12 -08:00
2026-02-20 11:57:19 -08:00
< footer >
2026-02-19 21:12:12 -08:00
< ul >
< li >
< a href = "/colophon" title = "colophon" aria-label = "colophon" >
colophon
< / a >
< / li >
< li >
< a href = "/" title = "go home" aria-label = "go home | hello hello from Lee Cattarin in 2026" >
hello hello from Lee Cattarin in 2026< / a >
< / li >
< li >
< a href = "https://heckin.technology/inherentlee/leecat.art" title = "source code" aria-label = "source code" target = "_blank" rel = "external" >
src
< / a >
< / li >
< / ul >
< / footer >
2026-02-20 11:57:19 -08:00
<!-- This page `/keffiyah - fishing - net - pattern/` was built on 2026 - 02 - 20T19:56:59.724Z -->
< body >
< / body > < / body > < / html >