Skip to content

Commit 0058c38

Browse files
committed
fix somethings in projects layout
1 parent 5c968d9 commit 0058c38

2 files changed

Lines changed: 205 additions & 10 deletions

File tree

css/projects.css

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ body {
4747
transition: all 0.3s ease;
4848
display: flex;
4949
flex-direction: column;
50+
gap: 12px;
5051
height: 100%;
5152
}
5253
.project-card:hover {
@@ -57,8 +58,9 @@ body {
5758
display: flex;
5859
justify-content: space-between;
5960
align-items: center;
60-
margin-bottom: 15px;
61+
margin-bottom: 0;
6162
gap: 15px;
63+
min-height: 38px;
6264
}
6365
.project-category {
6466
background: #181818;
@@ -72,25 +74,65 @@ body {
7274
.project-tech {
7375
color: #888;
7476
font-size: 0.9rem;
75-
flex: 1;
76-
text-align: right;
77+
width: 100%;
78+
text-align: left;
79+
white-space: nowrap;
80+
overflow: hidden;
81+
text-overflow: clip;
82+
}
83+
84+
.project-tech-marquee {
85+
display: flex;
86+
align-items: center;
87+
gap: 0;
88+
width: max-content;
89+
animation: project-tech-marquee var(--marquee-duration, 14s) linear infinite;
90+
will-change: transform;
91+
}
92+
93+
.project-tech-item {
94+
flex: none;
95+
white-space: nowrap;
96+
}
97+
98+
.project-tech-item:first-child {
99+
margin-right: 0.5em;
100+
}
101+
102+
@keyframes project-tech-marquee {
103+
from {
104+
transform: translateX(0);
105+
}
106+
to {
107+
transform: translateX(calc(-1 * var(--marquee-item-width, 240px)));
108+
}
77109
}
78110
.project-card h2 {
79111
color: #ffffff;
80112
font-size: 1.5rem;
81-
margin-bottom: 10px;
113+
margin-bottom: 0;
114+
min-height: 3.1em;
115+
line-height: 1.55;
82116
}
83117
.project-card p {
84118
color: #888;
85119
font-size: 1rem;
86120
line-height: 1.6;
87-
margin-bottom: 15px;
121+
margin-bottom: 0;
122+
}
123+
124+
.project-description {
125+
display: flex;
126+
flex-direction: column;
127+
gap: 8px;
128+
flex-grow: 1;
129+
min-height: 0;
88130
}
89131

90132
.project-readmore-toggle-wrap {
91133
display: flex;
92134
justify-content: flex-end;
93-
margin-bottom: 14px;
135+
margin: 0;
94136
}
95137

96138
.project-readmore-toggle {
@@ -302,8 +344,9 @@ body.readme-open {
302344
display: flex;
303345
flex-wrap: wrap;
304346
gap: 8px;
305-
margin-bottom: 20px;
306-
margin-top: auto;
347+
margin: 0;
348+
min-height: 64px;
349+
align-content: flex-start;
307350
}
308351
.project-features span {
309352
background: rgba(255, 255, 255, 0.1);
@@ -320,7 +363,7 @@ body.readme-open {
320363
text-decoration: none;
321364
font-weight: 600;
322365
transition: color 0.3s ease;
323-
margin-top: auto;
366+
margin-top: 0;
324367
}
325368
.project-link:hover {
326369
color: #ffffff;
@@ -331,7 +374,14 @@ body.readme-open {
331374
justify-content: space-between;
332375
align-items: center;
333376
margin-top: auto;
377+
padding-top: 10px;
334378
width: 100%;
379+
min-height: 36px;
380+
}
381+
382+
.project-card > .project-link {
383+
margin-top: auto;
384+
padding-top: 10px;
335385
}
336386

337387
.project-demo-link {
@@ -350,7 +400,7 @@ body.readme-open {
350400
/* CORREÇÃO DO BOTÃO NO MOBILE */
351401
@media (max-width: 768px) {
352402
.project-readmore-toggle-wrap {
353-
margin-bottom: 10px;
403+
margin-top: 2px;
354404
}
355405

356406
.project-readmore-toggle {
@@ -387,6 +437,7 @@ body.readme-open {
387437
flex-direction: column;
388438
gap: 8px;
389439
width: 100%;
440+
padding-top: 8px;
390441
}
391442

392443
.project-link {
@@ -462,20 +513,51 @@ body.readme-open {
462513
.project-header {
463514
flex-direction: column;
464515
align-items: flex-start;
516+
justify-content: flex-start;
517+
min-height: auto;
465518
gap: 5px;
466519
margin-bottom: 10px;
467520
}
468521

469522
.project-tech {
470523
font-size: 0.7rem;
524+
white-space: nowrap;
525+
overflow: hidden;
526+
text-overflow: clip;
527+
max-width: 100%;
528+
}
529+
530+
.project-tech-marquee {
531+
animation: none !important;
532+
display: inline;
533+
}
534+
535+
.project-tech-item {
536+
display: none;
537+
}
538+
539+
.project-tech-item:first-child {
540+
display: inline;
471541
}
472542

473543
.project-card h2 {
474544
font-size: 1.1rem;
545+
min-height: 0;
546+
line-height: 1.4;
547+
}
548+
549+
.project-description {
550+
gap: 0;
551+
flex-grow: 0;
475552
}
476553

477554
.project-features {
478555
gap: 2px;
556+
min-height: 0;
557+
}
558+
559+
.project-actions {
560+
min-height: 0;
479561
}
480562

481563
.project-features span {
@@ -492,3 +574,13 @@ body.readme-open {
492574
margin-top: 5px;
493575
}
494576
}
577+
578+
@media (min-width: 769px) {
579+
.project-header {
580+
flex-direction: column;
581+
align-items: flex-start;
582+
justify-content: flex-start;
583+
gap: 8px;
584+
min-height: 58px;
585+
}
586+
}

js/projects-readmore.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,93 @@
230230
return markdown;
231231
}
232232

233+
function initProjectTechTicker() {
234+
const techNodes = document.querySelectorAll(".project-tech");
235+
236+
function isDesktop() {
237+
return window.matchMedia("(min-width: 769px)").matches;
238+
}
239+
240+
function prepareNode(node) {
241+
// Only prepare marquee for desktop
242+
if (!isDesktop()) {
243+
return;
244+
}
245+
246+
if (node.querySelector(".project-tech-marquee")) {
247+
return;
248+
}
249+
250+
const rawText = node.textContent.trim();
251+
node.textContent = "";
252+
253+
const marquee = document.createElement("div");
254+
marquee.className = "project-tech-marquee";
255+
256+
const itemA = document.createElement("span");
257+
itemA.className = "project-tech-item";
258+
itemA.textContent = "• " + rawText;
259+
260+
const itemB = document.createElement("span");
261+
itemB.className = "project-tech-item";
262+
itemB.textContent = "• " + rawText;
263+
itemB.setAttribute("aria-hidden", "true");
264+
265+
marquee.appendChild(itemA);
266+
marquee.appendChild(itemB);
267+
node.appendChild(marquee);
268+
}
269+
270+
function removeMarquee(node) {
271+
const marquee = node.querySelector(".project-tech-marquee");
272+
if (marquee) {
273+
const text = marquee.textContent;
274+
node.textContent = text;
275+
}
276+
}
277+
278+
function updateNode(node) {
279+
const marquee = node.querySelector(".project-tech-marquee");
280+
const firstItem = marquee ? marquee.querySelector(".project-tech-item") : null;
281+
if (!marquee || !firstItem) {
282+
return;
283+
}
284+
285+
const itemWidth = Math.max(40, Math.ceil(firstItem.scrollWidth));
286+
const pxPerSecond = 30;
287+
const duration = Math.max(8, itemWidth / pxPerSecond);
288+
289+
node.style.setProperty("--marquee-item-width", itemWidth + "px");
290+
node.style.setProperty("--marquee-duration", duration.toFixed(2) + "s");
291+
}
292+
293+
techNodes.forEach(function (node) {
294+
if (isDesktop()) {
295+
prepareNode(node);
296+
updateNode(node);
297+
} else {
298+
removeMarquee(node);
299+
}
300+
});
301+
302+
let resizeTimeout = null;
303+
window.addEventListener("resize", function () {
304+
if (resizeTimeout) {
305+
window.clearTimeout(resizeTimeout);
306+
}
307+
resizeTimeout = window.setTimeout(function () {
308+
techNodes.forEach(function (node) {
309+
if (isDesktop()) {
310+
prepareNode(node);
311+
updateNode(node);
312+
} else {
313+
removeMarquee(node);
314+
}
315+
});
316+
}, 150);
317+
});
318+
}
319+
233320
function createReadMoreForCard(card, index) {
234321
const titleNode = card.querySelector("h2");
235322
const featuresNode = card.querySelector(".project-features");
@@ -250,6 +337,21 @@
250337
return;
251338
}
252339

340+
if (!card.querySelector(".project-description")) {
341+
const directParagraphs = Array.from(card.children).filter(function (child) {
342+
return child.tagName === "P";
343+
});
344+
345+
if (directParagraphs.length > 0) {
346+
const descriptionBlock = document.createElement("div");
347+
descriptionBlock.className = "project-description";
348+
card.insertBefore(descriptionBlock, directParagraphs[0]);
349+
directParagraphs.forEach(function (paragraph) {
350+
descriptionBlock.appendChild(paragraph);
351+
});
352+
}
353+
}
354+
253355
const toggleWrap = document.createElement("div");
254356
toggleWrap.className = "project-readmore-toggle-wrap";
255357

@@ -284,5 +386,6 @@
284386
}
285387

286388
const cards = document.querySelectorAll(".project-card");
389+
initProjectTechTicker();
287390
cards.forEach(createReadMoreForCard);
288391
})();

0 commit comments

Comments
 (0)