defuss-shadcn / Website / Resume & Portfolio / resume-entry
Resume EntryBLK
One line of a CV - a position, a degree, a talk - with when and where, the highlights and the skills it used; a promotion path at one employer, a timeline through the logos, or the dates in a column of their own. Part of the Resume & Portfolio blocks.
On this page (6)
§Experience
Logo or initials beside each entry, rules between them; title and organisation on the start side, when and where on the end side - narrow, they move under the title. The second entry is a promotion path: two roles at one employer.
§Timeline
data-variant='timeline': no rules - one line runs through the logos; an empty .mk-resume-entry-mark is a dot on it. Talks and volunteering fit the same entry.
§Horizontal
data-variant='horizontal': the entries side by side on one line through their marks, oldest first - a career at a glance; the date leads each entry. More entries than fit scroll sideways (scroll snap); on paper they stack.
§Projects
The timeline and the work in one view: .mk-resume-entry-projects holds Project Items under each entry - what came of the role, newest first. The project titles are h4, one level below the role.
§Columns
data-variant='columns': the classic CV - when in a column of its own on the start side, no logos. Narrow, the column folds back under the title.
§CSS view file
/* -- Resume Entry (website · Resume & Portfolio) -------------------------- One line of a CV - a position, a degree, a volunteer role, a talk: the title, the organisation, when and where, a sentence, the highlights and the skills it used; several roles at one employer as a promotion path. Entries with a logo and rules between them (default), on a line through their logos (timeline), or with the dates in a column of their own (columns, the classic CV). The list is a container: narrow, the dates move under the title - no breakpoints, no script. */@layer components { /* every box in the block measures border-box - the same on any page */ :where(.mk-resume-entries, .mk-resume-entries *, .mk-resume-entries ::before, .mk-resume-entries ::after) { box-sizing: border-box; } .mk-resume-entries { container: mk-resume-entries / inline-size; display: grid; width: 100%; margin: 0; padding: 0; list-style: none; } .mk-resume-entry { position: relative; display: grid; grid-template-columns: 2.75rem minmax(0, 1fr); column-gap: 1rem; padding-block: 1.25rem; &:first-child { padding-block-start: 0; } &:last-child { padding-block-end: 0; } & + .mk-resume-entry { border-block-start: 1px solid var(--border); } /* no logo: the body takes the row */ &:not(:has(> .mk-resume-entry-mark)) { grid-template-columns: minmax(0, 1fr); } } /* the organisation's logo (an <img>) or its initials (a <span>); an empty span is a dot */ .mk-resume-entry-mark { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--muted); color: var(--muted-foreground); font-size: 0.875rem; font-weight: 600; object-fit: cover; } .mk-resume-entry-mark:not(img):empty { justify-self: center; width: 0.875rem; height: 0.875rem; margin-block-start: 0.3rem; border: 0; border-radius: 50%; background: var(--primary); } .mk-resume-entry-body { display: grid; align-content: start; gap: 0.625rem; min-width: 0; } /* title and organisation on the start side, when and where on the end side */ .mk-resume-entry-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.125rem 1rem; & > .mk-resume-entry-title { grid-column: 1; grid-row: 1; } & > .mk-resume-entry-org { grid-column: 1; grid-row: 2; } & > .mk-resume-entry-when { grid-column: 2; grid-row: 1; text-align: end; } & > .mk-resume-entry-where { grid-column: 2; grid-row: 2; text-align: end; } } .mk-resume-entry-title { margin: 0; font-size: 1rem; font-weight: 600; line-height: 1.35; text-wrap: balance; } /* the organisation and the kind of engagement, dot-separated */ .mk-resume-entry-org { display: flex; flex-wrap: wrap; gap: 0 0.5rem; margin: 0; font-size: 0.875rem; & > * + *::before { content: "·"; margin-inline-end: 0.5rem; color: var(--muted-foreground); } & > :not(:first-child) { color: var(--muted-foreground); } & a { color: inherit; font-weight: 500; text-decoration: none; &:hover { text-decoration: underline; text-underline-offset: 3px; } } } .mk-resume-entry-when, .mk-resume-entry-where { margin: 0; color: var(--muted-foreground); font-size: 0.8125rem; line-height: 1.5; } .mk-resume-entry-when { font-variant-numeric: tabular-nums; white-space: nowrap; } .mk-resume-entry-text { max-width: 44rem; margin: 0; color: var(--muted-foreground); font-size: 0.9375rem; line-height: 1.6; text-wrap: pretty; } .mk-resume-entry-highlights { display: grid; gap: 0.25rem; max-width: 44rem; margin: 0; padding-inline-start: 1.125rem; font-size: 0.9375rem; line-height: 1.55; & li::marker { color: var(--muted-foreground); } } /* the skills it used */ .mk-resume-entry-tags { display: flex; flex-wrap: wrap; gap: 0.375rem; margin: 0; padding: 0; list-style: none; & li { padding: 0.125rem 0.5rem; border-radius: 999px; background: var(--secondary); color: var(--secondary-foreground); font-size: 0.75rem; font-weight: 500; } } /* several roles at one employer: a promotion path on a short line */ .mk-resume-entry-roles { display: grid; gap: 1rem; margin: 0; padding: 0; list-style: none; & > li { position: relative; display: grid; gap: 0.25rem; padding-inline-start: 1.25rem; &::before { content: ""; position: absolute; inset-block-start: 0.45rem; inset-inline-start: 0; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--muted-foreground); } &:first-child::before { background: var(--primary); } &:not(:last-child)::after { content: ""; position: absolute; inset-block: 1.2rem -0.8rem; inset-inline-start: calc(0.25rem - 1px); width: 2px; background: var(--border); } } } .mk-resume-entry-role { margin: 0; font-size: 0.9375rem; font-weight: 600; } /* timeline: no rules - one line runs through the logos */ .mk-resume-entries[data-variant="timeline"] { & > .mk-resume-entry { padding-block: 0 1.75rem; border-block-start: 0; &:last-child { padding-block-end: 0; } &:not(:last-child)::before { content: ""; position: absolute; inset-block: 3.25rem 0.5rem; inset-inline-start: calc(1.375rem - 1px); width: 2px; background: var(--border); } &:has(> .mk-resume-entry-mark:not(img):empty):not(:last-child)::before { inset-block-start: 1.6rem; } } } /* columns: the classic CV - the dates in a column of their own, no logos */ .mk-resume-entries[data-variant="columns"] { & > .mk-resume-entry { grid-template-columns: minmax(0, 1fr); padding-inline-start: 9.5rem; } & .mk-resume-entry-mark { display: none; } & .mk-resume-entry-body { position: relative; } /* the body is a grid AND the date's containing block: the head's grid placement would pick its area */ & .mk-resume-entry-head > .mk-resume-entry-when { position: absolute; grid-area: auto; inset-block-start: 0.1rem; inset-inline-start: -9.5rem; width: 8rem; color: var(--foreground); font-weight: 500; text-align: start; white-space: normal; } } /* narrow: when and where move under the title, the date column folds in */ @container mk-resume-entries (max-width: 34rem) { .mk-resume-entry-head { grid-template-columns: minmax(0, 1fr); & > .mk-resume-entry-title, & > .mk-resume-entry-org, & > .mk-resume-entry-when, & > .mk-resume-entry-where { grid-column: 1; grid-row: auto; text-align: start; } } .mk-resume-entries[data-variant="columns"] { & > .mk-resume-entry { padding-inline-start: 0; } & .mk-resume-entry-head > .mk-resume-entry-when { position: static; width: auto; color: var(--muted-foreground); font-weight: 400; } } } /* horizontal: the entries side by side, left to right on one line through their marks; more than fit scroll sideways */ .mk-resume-entries[data-variant="horizontal"] { grid-auto-columns: minmax(14rem, 1fr); grid-auto-flow: column; padding-block-end: 0.75rem; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; & > .mk-resume-entry { grid-template-columns: minmax(0, 1fr); row-gap: 1rem; align-content: start; padding: 0 1.5rem 0 0; border-block-start: 0; scroll-snap-align: start; &:not(:last-child)::before { content: ""; position: absolute; inset-block-start: calc(1.375rem - 1px); inset-inline: 3.25rem 0.5rem; height: 2px; background: var(--border); } &:has(> .mk-resume-entry-mark:not(img):empty):not(:last-child)::before { inset-block-start: calc(0.7375rem - 1px); inset-inline-start: 1.375rem; } } & .mk-resume-entry-mark:not(img):empty { justify-self: start; } /* the date leads, the rest stacks under it */ & .mk-resume-entry-head { grid-template-columns: minmax(0, 1fr); & > .mk-resume-entry-when { grid-column: 1; grid-row: 1; color: var(--primary); font-weight: 600; text-align: start; } & > .mk-resume-entry-title { grid-row: 2; } & > .mk-resume-entry-org { grid-row: 3; } & > .mk-resume-entry-where { grid-column: 1; grid-row: 4; text-align: start; } } } /* the projects of an entry: Project Items in a grid under it - the timeline and the work in one view */ .mk-resume-entry-projects { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 11rem), 1fr)); gap: 1.25rem 1rem; margin: 0.25rem 0 0; padding: 0; list-style: none; } /* -- Print ------------------------------------------------------ */ @media print { .mk-resume-entry { break-inside: avoid; } /* on paper the horizontal line stacks: nothing may hide in a scroll box */ .mk-resume-entries[data-variant="horizontal"] { grid-auto-flow: row; overflow: visible; & > .mk-resume-entry { padding-block-end: 1rem; } & > .mk-resume-entry::before { display: none; } } .mk-resume-entry-tags li { border: 1px solid var(--border); background: none; } } /* -- Accessibility ------------------------------------------- */ @media (prefers-contrast: more) { .mk-resume-entry-org > :not(:first-child), .mk-resume-entry-when, .mk-resume-entry-where, .mk-resume-entry-text { color: var(--foreground); } .mk-resume-entry-tags li { border: 1px solid var(--foreground); } } @media (forced-colors: active) { .mk-resume-entry-tags li, .mk-resume-entry-mark { border: 1px solid CanvasText; } .mk-resume-entry-mark:not(img):empty, .mk-resume-entry-roles > li::before, .mk-resume-entry-roles > li::after, .mk-resume-entries[data-variant="timeline"] > .mk-resume-entry::before, .mk-resume-entries[data-variant="horizontal"] > .mk-resume-entry::before { forced-color-adjust: none; background: CanvasText; } }}Comments, ideas or improvements? Edit this page's source on GitHub