Improving UX by Modaling Portfolio Details
I modalized the portfolio work details so they can be viewed without page transitions. About HTML acquisition using DOMParser and pitfalls during implementation.
Hello! I'm PanKUN.
Until now, clicking a work from the "Portfolio List" on this site would transition to a detail page (portfolio/xxxx.html).
However, people who come to see the portfolio probably want to "zap through various works". Operations like "click to move to details" -> "back with browser back" -> "scroll again to the next work..." are quietly stressful.
So I modified it to display detailed information in a modal window superimposed while maintaining the list page.
Implementation Policy
This site generates static HTML files from Markdown files using build tools.
Portfolio detail pages already exist as actual files like portfolio/work_01.html.
There is also a method of packing all information into JSON data and building it with JS, but "reusing already generated HTML of detail pages" is less wasteful in terms of SEO and build flow.
Process Flow
- User clicks a card.
- JS
fetches the detail page URL (portfolio/xxxx.html). - Parse the retrieved HTML text and extract only the content part inside.
- Throw it into the modal.
Technical Points
1. Fetch HTML and Parse
What can be obtained with fetch is just a "string". Use DOMParser to handle this as a DOM element.
// Get HTML
const res = await fetch(contentPath);
const text = await res.text();
// Parse string as HTML document
const parser = new DOMParser();
const doc = parser.parseFromString(text, "text/html");
// Extract only the necessary part (.work-detail)
const detail = doc.querySelector(".work-detail");
// Insert into modal
modalContent.appendChild(detail);With this, you can embed content seamlessly without using iframe.
2. Trap of Relative Paths
Since detail pages are built on the premise that they are under the portfolio/ directory, paths for images etc. are like ../assets/img/....
If you display this as is in the modal of the top page (root hierarchy), the links will be broken.
Therefore, I performed path rewriting processing on the extracted DOM.
// Fix paths starting with "../"
function fixPaths(element) {
const nodes = element.querySelectorAll('[src], [href]');
nodes.forEach((node) => {
// Attribute value acquisition and replacement processing such as removing "../"
// ...
});
}Stuck Point: Content Not Displayed?
When I implemented it and tried to move it, a phenomenon occurred where the modal opens but the content is pure white. Looking at the developer tools, the element exists, but it is not reflected on the screen.
Cause: Scroll Animation
The cause was the class reveal-on-scroll used on the detail page side to "display softly when scrolled".
.reveal-on-scroll {
opacity: 0; /* Initially transparent */
transform: translateY(20px);
/* Becomes opaque with .is-visible when scrolled into screen */
}When displaying as a detail page, the scroll detection script works, so there is no problem, but
when inserted into the modal, that script does not move, and it ended up waiting with opacity: 0 forever.
Solution
I decided to remove this class before inserting it into the modal.
const detail = doc.querySelector(".work-detail");
// Force display by removing animation class
detail.classList.remove("reveal-on-scroll");With this, it is now displayed safely.
Summary
I think the viewing experience (UX) of works has improved considerably with this modification.
- Can view crisply because there is no page transition.
- Easy to search from where you left off because the scroll position of the list is maintained.
- Direct links to detail pages (SEO) are also maintained.
Without giving up "because it's a static site", by using JavaScript well, I was able to realize rich behavior like a dynamic site.
Loading comments...