This is a reimagining of the 'Space Tourism Website' project that utilizes more advanced technologies such as React, React Router v6, and Tailwind. In addition to the previously used technologies like HTML, CSS, JavaScript, and JSON. These enhancements have significantly simplified the development process, transforming the page into a Single Page Application (SPA) with customized routes and subroutes for each section. This allows for an enhanced experience with reduced loading times. While maintaining its responsive design, the new version draws inspiration from the movie 'Interstellar' to provide a distinctive touch.
Vlad
@vladmeeAll comments
- @SFCC5555Submitted over 1 year ago@vladmeePosted over 1 year ago
Wow, you came up with your own version inspired by Interstellar! That definitely caught my eye
I like the way you are handling React. Your project has a good structure. You are making good use of NavLink to navigate between routes. And you manage to put together everything with very little CSS (really, I'm impressed!) All thanks to Tailwind, of course, which you seem to have good knowledge of. Well done!
The only feedback I have for you is regarding the responsiveness of your pages. While it's following the design on desktop and mobile, you skipped one step: tablet view :)
This can be quickly fixed with media queries but I want to give you a bigger challenge. Lately I'm reading about the "Fluid design" where, instead of targeting specific resolutions and not caring about anything in between, in this new approach you structure ALL your CSS with dynamic units so it adapts to ANY type of screen.
This can be achieved using only dynamic units (rem, vw, vh, %) and, the thing that actually changed my perspective a lot:
clamp()
where you can set a min and max value along with a recommended dynamic value so you have adaptive sizing from mobile (min) to desktop (max) and everything in between (recommended). Here's an example:Instead of:
.technology .navLink { width: 40px; height: 40px; } @media screen and (min-width: 640px) { .technology .navLink { width: 60px; height: 60px; } }
You can use clamp() and ditch the media queries:
.technology .navLink { width: clamp(40px, 5vw, 60px); height: clamp(40px, 5vw, 60px); }
Hope my feedback helps! As a I already mentioned your solution is already great, it's just the small details to make it perfect for any type of screen. Keep it up!
Marked as helpful0 - @NathLoweSubmitted over 1 year ago
Final Design of the challenge guys. it has been great coding these website and your support was really helpful. Thank you so much for following through this journey.
@vladmeePosted over 1 year agoHey Nathan, you have the most comprehensive solution using Next.js! Or at least the best I've checked so far :D
I used Next.js for this challenge too and I was looking for a similar tech stack for comparison. Well... I was amazed by your code: it's well-structured and easy to read, you make good use of tailwind and motion, and generally, I have a lot to learn from it.
To give back, I have a few suggestions for you as well:
I realized that most of your pages are straight-up Client components. Your application is not really taking advantage of the SSR capabilities of Next.js. My approach was to keep each page a Serve component with as much static content as possible then include the dynamic content as a Client component. In this way, each page will have its own metadata, plus the background, title, and data can load faster leaving for the browser to render the content.
You are using the Image component from Next.js but you're applying Tailwind classes right away, without using its built-in attributes that could make your images responsive by default. Actually, on the Crew page, on a laptop screen, the image overflows under the navbar. Not a big problem but with the addition of these two attributes you can make sure that the image always fits in its container:
<Image fill={true} style={{ objectFit: 'contain', objectPosition: 'center bottom' }} />
Hope this helps! As I already mentioned, I feel that your solution is already superior from many point of views, these are just some small details that could only make it even more perfect. Keep it up!
Marked as helpful1 - @AaronNevalinzSubmitted over 1 year ago
- difficulty in centering the container harboring the QR-code image and the description
How do you best center a div in a div?
@vladmeePosted over 1 year agoHi! Flexbox is great for this as already mentioned but I would like to give you an alternative, using grid:
display: grid; place-items: center;
Grid feels more intuitive in this case as it's designed for arranging elements in a two-dimensional space, controlling layout both horizontally and vertically for complex structures.
Flexbox, on the other hand, is a one-dimensional model for aligning items in either a row or column. But it works if you think of the page as one big row where you position your item in the middle of the row, and align it vertically as well.Grid would be desired though!
1 - @Y-aburobSubmitted over 1 year ago
that was easy :D
@vladmeePosted over 1 year agoNeat!
One small thing! On mobile, you are forcing a fixed height on the image:
.qr img { height: 300px; }
While the width is still in percentage:
.qr img { width: 95%; ... }
This skews the image a bit. Make sure you maintain its ratio across all resolutions. Either with fixed pixel values or you can experiment with vw/vh.
Other than that everything is excellent. I feel from you that you got a good understanding of how to properly structure your CSS. Keep it up!
Marked as helpful0 - @MladenAnticSubmitted over 1 year ago@vladmeePosted over 1 year ago
Your solution is really neat! Well-structured SCSS, rem everywhere, everything makes sense. Not sure what to comment here... Great job!
If I may, I will mention only one thing:
The header line:
.header__line { width: 35%; height: 0.0625rem; margin-right: -6.25rem; }
Adding a negative margin right here only moves the line to the right, it doesn't stretch it. This doesn't give you control over where it starts or where it ends.
Yes, you added the same amount in padding to the navbar:
.header__navigation { @media screen and (max-width: 62rem) { padding: 0 6.25rem; }
But I think there's a better solution. Instead of moving the line (which can overlap the content if not calculated properly) better move the elements that are strictly decorative: the navbar background!
Keep your structure of: LOGO - LINE DIVIDER - NAVBAR CONTENT
Then, add the blur background as a pseudo element to the navbar (::after) and, instead of moving the line on top of it, stretch the background under the line.
In this way, if things don't match perfectly, you know that the content will never be affected or overlapped. It's just a blur background that can be as short or as long as it can be. Plus, now the line starts exactly after the logo where you wanted ti!
Hope this was helpful, it's just a very small caveat in an excellent implremention of this project! Keep it up!
Marked as helpful1 - @barbaradamasdevSubmitted over 1 year ago
I did transition on cards to be more interactive. I loved to do this challenge. Really excited about the result.
Any feedback will be amazing!
@vladmeePosted over 1 year agoGreat job! Your project looks excellent, almost pixel-perfect!
I like that you added extra stuff, I noticed the flip animation on the mobile menu toggle. That's a nice touch!
The animation on the tabs is nice too but, as @Cor-Ina already mentioned, this is not really a UX improvement. Yes, users prefer reduced motion, but another thing you should consider here is to not move the controls. The tab buttons should always be predictable for the user. Imagine someone wanting to check all options before making a decision. They would want to click on each tab in a sequence. In your solution, their tab buttons run away before they can click. They are coming back but the brain tells you something else until the animation is done. You know what I mean, right?
In this case, I would consider other types of animations and only affecting the content (image, text etc.) elements that change! You can have the text blink (opacity animation) or reveal top to bottom (size animation). That's actually a UX improvement because the user will be aware that those elements updated and she needs to read it again. Hope that makes sense! Let me suggest animista which is a nice collection of CSS animations.
And, if you want to bring it to another level you could even have the elements revealed in a sequence, one by one. That would be a great practice for you if you haven't played with delay and triggers before!
Other than that you nailed it. It looks exactly like the designs! Maybe revise your CSS a bit. I've seen a few things like
max-width: 110vw;
This translates to: this element's width can't be more than 110% of the viewport width which is... impossible unless you have horizontal scroll (not advised!) So I think this line doesn't have any effect.Keep up the good work! Looking forward to seeing your next projects!
Marked as helpful1 - @jamesekunolaSubmitted over 1 year ago
I thoroughly enjoyed working on this project, although I did encounter some challenges on the technology page. One specific hurdle was determining how to appropriately display portrait or landscape images based on the user's screen size. I would greatly appreciate any feedback on what additions you believe should be made to the page.
@vladmeePosted over 1 year agoLooks great! You followed the design almost 1-on-1. Even added an animation to display the destination content. That's impressive!
I see you successfully displayed different portrait or landscape images using media queries, anything you want to ask about that?
I like the image slider on the crew page. That's a nice touch. I would like to suggest something here. For the images instead of object-fit: cover I would add contain:
.image img { object-fit: contain; }
In this way, you make sure the image is not being cropped out, especially here where you are displaying portraits of people. I know that you already added
object-position: top;
which makes sure their heads are never cropped out (which is very thoughtful!) but you should always aim to display the data in the best possible way!On another note, I think you overengineered the mobile nav. Using context is not fully necessary, you can handle the toggle with a simple useState inside the component. Unless.. you wanted to practice context in which case everything is neat!
Oh, before I hit send, you forgot to add the interaction for the EXPLORE button on the homepage. It should have a pretty nice animation on hover too.
Looking forward to seeing your updated solution! Practice makes it perfect!
Marked as helpful1 - @AdityaSurveSubmitted over 1 year ago@vladmeePosted over 1 year ago
Almost perfect solution! Well done!
I like your motion implementation. It adds a nice effect on navigation!
All pages are following the designs in detail. Small glitches with the navigation on mobile (/crew and /technology), you might want to have a look at that.
Other than that, I was distracted by the misalignment on your home page. You seem to be using flex, which is great but you're not aligning the elements as instructed. If you can tell from the designs, the SPACE col is placed in the bottom left corner and the EXPLORE button in the bottom right corner.
A solution using flex is like:
.container { display: grid; grid-template-columns: 1fr 1fr; } .space-col { align-self: end; justify-self: start; } .explorer-btn { align-self: end; justify-self: end; }
Assuming that the container is full width and full height, which can be achieved either with
calc(100vh - nav)
or placed in a parent that is 100vh and set the containerflex-grow: 1
Hope this is useful! Don't let yourself let down about it, it's a very small detail and your solution is definitely well-coded!
Marked as helpful1 - @faisalahmed11Submitted over 1 year ago
- Any feedback is welcome :)
@vladmeePosted over 1 year agoI used Next.js for this challenge as well! Great job!
I like how you're adding the user's choice in the URL. That's a nice touch!
I see you're having a loading state. That's nice, is it really needed? (Serious question)
A few things that I realized when exploring your solution:
You are targeting specific images here to fine-tune them:
.crewImage[alt="Douglas Hurley"] { top: 3rem !important; height: 71.2rem; margin-top: -3rem !important; margin: 0; } .crewImage[alt="Mark Shuttleworth"] { height: 65.4rem; } .crewImage[alt="Victor Glover"] { height: 68.1rem; } .crewImage[alt="Victor Glover"] { height: 60.7rem; }
I wouldn't do that. You should always think of your style and structure to fit almost any kind of data as it would be served from a server. Yes, it won't be perfect for all types of images, but you have 4 samples to build your abstract solution around.
On another note, your globals reset is pretty thin. That's why you have to do this:
> ul { list-style: none;
Overall a great adaption. Good folder structure. Following the design assets perfectly. Keep it up!
Marked as helpful1 - @IryDevSubmitted over 1 year ago@vladmeePosted over 1 year ago
Wow, I was highly impressed by the dynamic background, the spinning planets, and the small details like the tabs underline effect.
Your solution is nearly perfect so I would only make a few isolated comments:
Your mobile navigation menu doesn't close after the user navigates elsewhere. Luckily it's a quick one to solve, you only need to update the menu on click:
<NavLink to="/" onClick={updateMenu} > <span>00</span> Home </NavLink>
I think you overengineered a bit here. You don't need this:
setBurgerClass("burger clicked"); setMenuClass("navbar mobile-menu");
You can have only one variable like:
const [isMenuOpen, toggleMenu] = useState(false);
And set your classes according to it:
<img className={`${isMenuOpen ? 'burger unclicked' : ''} other-classes`} src={burger} onClick={updateMenu} alt="hamburger menu" />
This is how you can smartly use React!
And it can apply in other cases as well. For example, here's how you can easily display a list of elements:
{listOfElements.map((element, index) => ( <div key={index} data-index={index} onClick={techChange} className={`num ${index === 0 ? 'num-active' : ''}`} > {element} </div> ))}
Overall it's a great solution from the styling standpoint. I can't send this comment without complimenting your CSS skills, the smart use of rem/vh units, grid, and the great structure of your SCSS files. Keep it up!
Marked as helpful1 - @fsp3012Submitted over 1 year ago
It was difficult to fetch the data from the json file provided so I had to change tot a js and export it. Check and review and leave a comment on how i can do better, i look forward to seeing your comments. Thanks
@vladmeePosted over 1 year agoGreat work! Your solution is complex, demonstrating effective use of React templating, Tailwind classes, and data fetching from JSON. Here are just a few small things you can improve on:
1.I noticed your tabs don't showcase an active state. It's important to highlight the user's selection, right? This could be done by adding a conditional class to your button element, like so:
className={`${index === value ? 'border-b-2' : ''} other-classes`}
2.Your mobile menu doesn't seem to close after a user navigates elsewhere. Luckily, you already have a handleClick function that can remedy this. Simply invoke it when the Link element is clicked:
<Link onClick={handleClick} className="md:hover:border-b-2 pb-5" to="/"> 00 HOME </Link>
3.I've noticed extensive use of the !important directive in your CSS. Keep in mind, this should ideally be a last resort, typically when styling a third-party element where its code is inaccessible. Given that you're using Tailwind and custom CSS, it's unlikely to be necessary. To rectify this, I suggest removing all instances of !important, then addressing any design inconsistencies that arise. This might even involve stripping back the classes and rebuilding the elements' styling, which could be a great learning experience.
I must compliment your proficiency with Tailwind. You clearly have a good understanding of its classes and the final result is excellent. Your handling of React is great too. Despite this being a small project, the structure is well organized. Keep up the good work!
0 - @khophisnowSubmitted over 1 year ago
All feedback is Welcome. Thank You.
@vladmeePosted over 1 year agoGood work! Your HTML structure is well-thought-out, and the CSS adheres to best practices. That said, I do have a few observations:
1.Some elements, like the Explore (large) button, don't resize across different devices. It could be beneficial to use media queries or, even better, viewport units (vw) to manage element sizing.
2.@ALI-KHALED-13 has already pointed this out, but the tablet view doesn't quite match the design instructions.
3.The padding around the content appears a bit thin. It might be worth revisiting.
On a positive note, I'm a fan of how you've started your CSS with variables, resets, and utility classes. Your naming conventions are clear and consistent, and the smart use of rem and clamp across all elements is commendable. The use of media queries in em is super impressive.
Overall, it's a solid effort. I'd suggest spending a bit more time refining the responsiveness to polish it up. Keep up the good work!
0