Codepen and Questions

I’m trying to learn CodePen to make it easier to share my code here.First CodePen
I hope this works. If you can see my CodePen, refer to it for my questions.

As you can see, I didn’t exactly get the CodePen in the right place to make it appear below my post. I need instructions, please.

Getting past the CodePen issues, my questions about my code are these.

The code that formats these images is from PaulOB but I modified it in trying to learn from it (so all errors are mine). I mention this to explain that I don’t understand all of the code
) There is HTML, <div class="birth-details-container offset heading"> that confuses me. Nowhere in the CSS (that I can find) is there a ".birth-details-container" class declared. I’ve never seen or read about concatenating classes. The same occurs for the next 2 screen containers, (marriage and death). What does a) using concatenated classes do and b) where can I learn more about concatenating class selectors?

  1. Paul mentioned that he places code at the start of all his CSS files like this:
html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
html,
body {
  margin: 0;
  padding: 1rem;
}

I’m trying to understand what the declarations accomplish and why to use them.
a) From searching I found that setting box-sizing: border-box; causes margins and padding to be included in the width and height of a container; here they are assigned to the entire HTML tag . . . meaning (I infer) that the rule applies to to all containers in the document unless explicit code overrides it. Is that the case? Is this done so that taking care of box sizing can be skipped as one adds more code one doesn’t have to include box-sizing: border-box; multiple times?

b) Fom searching; :before and :after insert content before and after the pseudo code elements they modify; Paul then uses them in CSS with the h1, h2 .title selectors:

h3.title:before,
h3.title:after {
  content: "";			
  flex: 1 0 0;
  height: 1rem;
  border-top: 1px solid #000;
  transform: translateY(1rem);
}
h3.title:before {
  max-width: 1.5rem;
}

I don’t understand what’s going on or how it works. Here’s how I interpret it: .title is used to define where the box titles are placed similar to the way fieldset legends are placed; the content: "" property inserts generated content defined by the pair of double quotes, but what do the double quotes do? If they put spaces before and after the titles, what determines how many spaces and where they are placed relative to the container vertical border? The transform: translateY (1rem) declaration (from searching allows for rotating, scaling, moving or skewing content and translateY(1rem) moves an element on the Y-axis by 1rem (I think). What does the flex: 1 0 0 do? From searching, ‘flex’ is shorthand for defining how content grows or shrinks in containers; what do 1 0 0 refer to and what do they do? I don’t understand the syntax.

  1. How does one make grid columns of unequal width using fr (fraction)?

  2. I added HTML content to column 3 (bio-container) making it much larger vertically: column 2 containers (birth / marriage / death) increased in height. Before my changes to column 3 (bio-container), Paul’s code had the column 2 containers wrapping around content but not growing vertically. I don’t know what I did to change that.

Thanks for your patience.

1 Like

As we can see…what?

(and yes, the codepen works…)

1 Like

It looks like the codepen is working - you’re a step better off than I, as I’ve never tried it!

I see that all your titles have text that starts behind them. That’s caused by your css definition of .title (line 295) having position:absolute. Absolute positioning is a bit tricky, as it takes the element “out of the flow” of the rest, and treats it as if it were a separate layer. Thus all the following text starts at the top of the container. If you remove the position:absolute from the .title definition, it looks more correct, though it will also ignore your top & left positioning; if you still want to position the top & left, you could use position:relative and then top & left will work, though they will be moving the titles relative (i.e. an offset) to the default position.

1 Like

As you can see the codepen shows up as a link instead of as an image below my post like other codepens I’ve seen here do. I don’t know how to make a codepen appear below my post.

Thanks, tracknut.

This business of manipulating titles to appear within the top borders of objects is all new to me. I’m trying to learn how to do it. I have never used the position declaration.

I think that was a recent change… not sure it was by choice or not.

An element can belong to multiple classes, separated by space. An element with class="A B C" belongs to 3 classes - class A, class B, and class C. When you come to messing about with classes in javascript, you’ll find the property is called classList - which IMO is a better descriptor. The class attribute specifies a list of classes, separated by spaces.

CSS will apply to any matching element; So in our element’s case,

.A { 
  color: red;
}
.B {
  font-weight: bold;
}
.C {
  text-decoration: underline;
}

Our element would be a bold red with an underline, because it matches all 3 rules.

CSS rules can combine classes (or element type names, or IDs, or pseudoselectors, for that matter) - in this case, the element matches only if it belongs to all classes of the rule. Concatenation is done by having no space between designators

So

.A.B {
  color: red;
}
.C.D {
  font-weight: bold;
}

Our element would be red, but not bold; it is a member of both A and B, so the red applies; it is a member of C, but not of D, so the second rule does not apply to it. div.findme would apply a rule to things with the findme class, but only if they are div elements.

Combined CSS rules in this way will be constructed with element first, then class(es), then id, then pseudoselectors. div.A#myid:before (Strictly speaking, the only requirement afaik is that the element goes first if there is one. Old IE versions used to have a requirement of Class before ID, but I believe they ditched that somewhere around IE 7.)

* as a CSS rule matches all elements within its context (By default, the context is ‘the entire document’)

*:before, as a psuedo-element selector, targets all elements’ :before pseudo-element components.

CSS rules have structure, and can be hooked together with meaningful combinators.
an unmodified space between selectors means “descendent” (div p targets p’s that are the descendents of div, at any depth.)
a > means “direct child” (div > p targets ps who have a div as their immediate parent.)
a + means “immediately following sibling” (div + a targets a link who is the next sibling after a div. [Sibling means they have the same immediate parent.])
a ~ means “any following sibling”.
a , in a CSS file means that you’re assigning a single set of transformations to multiple selectors. Functionally, an “or”. (a,div will apply the rule to all links, and all divs.)

2 Likes

That’s a lot to digest. I’ll give it a go tomorrow when I’m rested.

If you would have paid attention before you edited, it WAS working (I had fixed it for you) but you broke it again :lol:

An inline like you did just shows the link.

But the link on it’s own line (and without the preview text) will “onebox” (the term for showing the preview)

Thanks for sharing your CodePen! I can see it just fine. :blush:

Regarding your question: when you see something like <div class="birth-details-container offset heading">, that’s not a single class — it’s actually three separate classes applied to the same element. Each class can have its own styles in the CSS. So you’re not seeing a .birth-details-container rule because it might not be defined, or it’s relying on the shared styles from offset or heading.

To learn more about this, search for “multiple classes in HTML” or “CSS class selectors” — MDN Web Docs is a great place to start.

Let me know if you’d like help digging into the CSS!

1 Like

You say my code has this:

<div class="birth-details-container offset heading">

But it does not have three classes it has two only.:slight_smile:

<div class="birth-details-container offset-heading">

I left the birth-details class in place in the html because that was your original reference and lets you know what it was used for. I added the class offset-heading so that I could use it on multiple similar elements without confusion. If I had used the class birth details container on your marriage-details-container it would be confusing. As it stands the offset-heading class is all that is used in the css but if at a later date you wanted the birth-details-container to be blue and the marriage-details-container to be red then you already have hooks in place in the html to achieve this simply.

.birth-details-container {background:blue}
.marriage-details-container {background:red}

@m_hutley has explained how multiple classes work and can be concatenated so I won’t answer those questions.

You are correct on one point and I already explained this in that the border-box-model is a more intuitive method to use because if you give an element 300px width and add 20px padding and 10px borders then the element will still fit inside another 300px container. You made this error numerous times in your original code and had overflows everywhere. In the default box model the inner element would in fact be 360px wide and not fit in a 300px container. You can read more here.

Note that box-sizing has no effect on margins as they are outside the box model.

You are also wrong when you say it applies to all containers as box-sizing only applies to the element it is applied to. No children will have that model. Therefore the part you missed out was this:

*,
*:before,
*:after {
  box-sizing: inherit;
}

The asterisk (the first rule above) is the universal selector and represents any (all) elements much like a wild card. What that rule does is to tell every element on the page to inherit the box-model from its parent. Therefore unless any specific over-rides have been made all elements will inherit the box model that I defined for the html element. The second and third rules are for the pseudo elements as they get missed by the universal selector and would have the wrong box model without that rule.

(As an aside note that not all rules in CSS are inherited automatically as that would be nonsense. Image you said margin:20px on your parent container and then every element inside inherited that margin also!)

Pseudo elements are part of CSS and of course should be part of your structured approach to learning CSS rather than jumping in at the deep end and having to learn everything in one go:). I mean its good that you are jumping in but with a complex layout you are asking yourself how to learn the whole of CSS in a pretty haphazard way. In a normal learning curve you would know what pseudo elements are already and I can then tell you why and how I used them. However, I need to explain what they are first and then explain why I made use of them. That’s a lot of information to take in :slight_smile:

In short the pseudo elements ::before and ::after are used to insert content before and after the existing content in that element ( they really should have two colons as that identifies them as pseudo elements and not pseudo classes but either will still work as originally only just one colon was used). If the element has no content they will still be added at the start and end of that element.

On its own :before will do nothing unless the content property is used so they always come as a pair.

e.g.

h3.title:after {
  content: "";	
}

That’s not a space its an empty string. It does nothing to the display but prepares it so that css can be applied and create something. You could actually use the string to display some trivial text.

e.g.

h3.title::before {
  content: "I am something at the beginning ";	
}
h3.title::after {
  content: " I am something at the end";	
}

So imagine an h3 that was like this:

<h3> HELLO </h3>

Then I apply those two rules above to it you will see on the screen this:

“I am something at the beginning HELLO I am something at the end”;

In most cases though you would not do that as real content should go in the html but for trivial content you can add text like that. The widespread use of :before and :after however is to use it like you would a couple of empty spans in the document and apply some decoration effects to it so that you don’t need trivial mark up in your nice semantic html.

So the best way to think of ::before and ::after is to imagine that an element has this structure.

<h3 class="title"><span></span> HELLO <span></span></h3>

Now if you gave the first span a class of .before you could say this:

span.before{
display:block;
background:red;
width:10%;
}

However with pseudo classes we don’t need a span in the html and can say:


.title::before{
content:"";/* we need the empty string to make a box we can use*/
display:block;/* just like spans the content property inserts and inline box but we need a block box in order to apply widths*/
background:red;
width:10%;
}

The transform moves the element downwards by 1rem without changing anything else. I did that so that the borders could sit on top of the background nicely because I already dragged the parent element upwards by 1rem with a negative margin-top. I did not use absolute positioning because my method was more robust and does not remove the actual text from the flow. (However the absolute positioning method could be used to the same effect.)

You are asking me to explain all of flex but that’s a job for you later :wink: but essentially it tells the element to take up all the available space. I use it on the pseudo element to draw the top lines of that box and create the effect shown in my example where the text can straddle both background unlike Dave’s method that uses a background to rub another background out.

This code:

h3.title:before,
h3.title:after {
  content: "";			
  flex: 1 0 0;
  height: 1rem;
  border-top: 1px solid #000;
  transform: translateY(1rem);
}
h3.title:before {
  max-width: 1.5rem;
}

Is almost the same as having this structure (as mentioned above):

<h3 class="title"><span></span> Birth <span></span></h3>

There’s basically 3 boxes in that structure and using flex I set the first part (the ::before element) to have a horizontal black border that will stretch but will not exceed 1.5 rem. The span at the end which would be the ::after part also has a horizontal border and the flex rule I gave it basically says now take up all the remaining space. So we get a small border followed by the Birth text followed by a border that goes all the way to the end. No need for any widths apart from limiting the first element otherwise it would take up as much space as available and in effect centring the text. Just look at my codepen to see the effect and the open devtools and toggle on and off certain properties in devtools to see what happens.

I already did that in my example:

grid-template-columns: 0.5fr 1fr 0.7fr;

1fr basically says take up 1fraction of the available space. If each column was 1fr then they all take up the same width. If one column is .5fr then it takes up half the available space left (after everything has been taken into consideration) and the others take up the rest depending on their values. In that way you let the browser work out what space is available but you specify which element should be bigger than the other. Forget about pixel widths as they are no use in a fluid layout like this. Look at my codepen to see the difference in column widths.

Please do not do the following ever again.:slight_smile:

.personal-pages-container {
  grid-template-columns: 250px 350px 225px;
}

That’s of no use at all and is too rigid a construct to ever be useful.

I also notice in your codepen that you changed the media to say 600px whereas mine was at 900px. That means your layout is completely broken from 900px and below (indeed in your code your layout breaks at about 990px). Also remember that if you then redefine any of the properties in that media query in code that is below the media query then you will over-ride it.

Don’t let your code get messy and keep things together.

For a responsive site all you need do is grab the edge of your browser window and go from the widest you can and then down to about 320px (although most phones are about 370px these days but the iphone 4 was 320px). If at any point the content overflows or you get a horizontal scrollbar on the viewport then you need to use a media query or a design change to fix it. There should never be a horizontal scroll bar on the viewport (unless its some sort of slideshow).

Lastly this has been mentioned previously you must have the viewport meta tag in place otherwise mobiles won’t react to the media queries properly.

<meta name="viewport" content="width=device-width, initial-scale=1">

You can add that in codepen by clicking on settings and going to the html menu of the pen settings and there is a box at the bottom prompting you to add the correct meta tag.

Also on codepen you don’t need the body tags as codepen already assumes that all code is inside the body.

Whew!! A lot to take in :slight_smile:

As I said previously you have re-entered a lot of the mistakes into your codepen that I was hoping you would avoid such as using widths when none is needed and saying things like width:100% and then margin-left:30px. How is 100% + 30px ever going to fit into a parent container. It will always overflow by 30px or stretch the parent depending on situation.

In your codepen you would need to modify the rules like this to get your top 3 columns back into some sort of semblance.

.personal-pages-container {
    grid-template-columns: .875fr 1fr .85fr;
}
.imgwrap img{
  width:100%;/* this is one time you do need a width otherwise the image is not responsive*/
  height:auto;/* you need this or aspect ratio may be lost*/
  padding:.5rem;
}
.birth-details-container,
.marriage-details-container,
.death-details-container{
  width:auto;
}
.photo-container{
  margin-left:0;
}
.life > div {
 margin-bottom:2rem
}

I didn’t fix your broken headings in those boxes because I already gave a good answer in my codepen so I’d just be repeating old ground. :slight_smile:

However I would suggest that you revert to my codepen only as it is much cleaner and does not have those logic errors :slight_smile:

2 Likes

For future notes;
the HTML box assumes you’re in a body tag.
the JS box assumes you’re in a script tag (technically it injects a src’d reference). This phantom tag is considered to be at the bottom of the HTML, so that it can access any elements in the DOM at the end of your HTML.
the CSS box gets stuffed into the head element by Codepen as an inline CSS declaration (which is part of the reason they dont want you to put header stuff in the HTML box).

2 Likes

Just post the link to codepen as plain text (like this comment) and do not use the editor link tag above.

1 Like

Thank you, Paul.

If I’m repeating the same mistakes, it means I’m not learning. That’s discouraging.

I have examined the code I received from you and tried to understand it. My approach has been to read the code then do some searching and reading online to find answers to things I don’t quite understand. Then I try to use your code - which sometimes entails making modifications - to see if I understand it. I haven’t discarded all the code that I wrote on my own (perhaps I should) but have incorporated lessons from you (some not well learned) into my code.

I think I will spend the day today searching my code for ‘width’, ‘height’, and ‘px’ and replacing them to determine what effects I can acheive.

I started yesterday to rework a page layout to conform it to other pages. I’ll discard all that work and start over after poring over today’s lessons. Another precept I think I will try to adopt is to keep my displays as simple as possible and forego bells and whistles (like titles) that I can do without. I can always come back to the designs later and fine tune them.

Again, thank you for your patience and for all the effort you put forth on my behalf.

:cowboy_hat_face:

1 Like

I was making such a mess of things I decided to start over with fresh CSS and HTML. This CodePen is the result. I tried to demonstrate that I had learned lessons taught here. Shown here is the beginning of a new home page HTML file with the styling I chose. What you see is the framework; photos and more caption content will be added. I thought I should probably pause at this point to ask questions. Here are some points (in no particular order):

  • I used concatenated selectors.
 <div class="parents-photo-heading photo-heading">Healy and Pa
      </div>

Grid coordinates are defined by parents-photo-headingwhile photo-heading defines text alignment and size. This was intentional but there might be (probably are) better ways to do this. I was demonstrating the use of multiple class selectors.
Did I use them right?

  • There are no width: or height: declarations in the CSS.
  • px appears only in max-width and border-radius: statements; if there is a better way to do so without using px I don’t know it.
  • The entire HTML file is included in the CodePen to show that the <meta viewport statement is in the <head>.
  • The margin-top: -.5rem; appears in the heading because content was not as close to the top container border as I wanted it to be. I could find not margins or padding that I could identify as causing the heading placement; so I used the margin statement to raise where it appears and as a point to ask why the heading would appear where it does without the -.5rem attribute. ???
  • The CodePen is untitled because I couldn’t find a way to give it one. What am I missing?
  • The font (Birthstone) I used is a Google font. It doesn’t render in the CodePen. I think this is because it is a special font and must be downloaded and installed to render as intended. Am I right?

Please comment on what I’ve done and point out things I still need to take into account.

At the top-left of the Codepen, the title of the Pen appears, and for the Author, there will be a little pencil symbol. That’s how you retitle it.

1 Like

After completing the code in the CodePen from the earlier post, I continued to work on the project. I’ve made a few tweaks to font size and layout, but nothing significant . . . mostly just confirming that I could make the changes.

Now, I want to insert the photos; but I’m running into problems. If you look at the HTML you will see that I added an img statement. On my system, the reference works and the image appears. The problem is that the image is too large and isn’t constrained to fit within the container (parents-photo) defined for it. This CodePen doesn’t demonstrate that because I don’t know how to make my image files available to CodePen (alternate text, ‘Parents,’ shows up instead). I tried using object-fit: contain; but that didn’t work on my system and, presumably, wouldn’t work in CodePen either.

I’m guessing here, but I think that there is nothing defined to contain the image within. In earlier coding, I was able to position the image exactly where I wanted it using width and height statements in CSS. I defined containers with dimensions in px for the container and was able to ‘place’ the image within the container. When I look at DevTools I see the container defined at row 2 / column 2 as parents-photo as it’s defined in the CSS. I don’t know why object-fit: contain; works with width and height explicitly defined but not when the container is defined by a grid. FWIW there is no grid height defined. The grid is defined by

.home-page {
  display: grid; /* 3 rows / 3 columns*/
  gap: 1rem 3rem;
  grid-template-columns: 0.4fr .6fr 1.25fr;
  grid-template-rows:
}

I searched and re-read the CSS grid tutorials but found nothing that told me what to do. I searched to learn how to constrain content (text, images, . . . whatever) to containers without success.

I guess the question for this post is: How do I constrain images into grid areas without resizing the images? If my grid row/column were coded with text, would it fit within the container? UPDATE: I copied a paragraph or 2 of Lorem Ipsum and pasted it into the div meant for the photo. Lo and behold! The lorem text was placed within the container and the container ‘grew’ to fit the text. I conclude, therefore, that there is something about inserting images into the grid coordinates that I need to learn.

FURTHER UPDATE:
In continuing to delve into this issue I found an article here at SitePoint by Ralph Mason. I learned that object-fit references a content box. Looking further, I learned that “CSS grid coordinates do not define a content box; instead, they specify the placement of grid items within a grid layout, which consists of rows and columns. The actual content box is determined by the dimensions and properties of the grid items themselves. - source; AI assist in duckduckgo search”. This leads me in circles,(I’m easily led, I guess :zany_face:.) I’m back where I started: How do I fit images into grid coordinates without resizing? Is there a way to turn grid coordinates into content boxes? Hmmmm.

My answer might lie in Mason’s Conclusion: " The object-fit property is designed to work with any kind of replaced elements, such as images, videos, iframes and embeds. Quite how useful it is to fit elements like videos into a defined area (where some of the element might be hidden) is perhaps a matter for debate, but no doubt there are viable use cases. A better option might be to set the width of an iframe to width: 100% of the available space and then use the aspect-ratio property to preserve its proportions."

The object fit property works on an image element and not the parent of the images but isn’t needed for what you want to do. I actually gave you the answer about three times already :slight_smile: and in just the last post I gave you this:

.imgwrap img{
  width:100%;/* this is one time you do need a width otherwise the image is not responsive*/
  height:auto;/* you need this or aspect ratio may be lost*/
  padding:.5rem;
}

So in your new code you need this:

.parents-photo img{
  width:100%;
  height:auto;
}

I have to go out so can’t answer your other questions but I see you are starting to make improvements. Back this afternoon :slight_smile:

1 Like

I’m a slow learner, Paul. Sorry.

This post (lesson?) forced me to revisit using the img qualifier in a selector definition. I found that I had used it in another project, but it was “monkey see / monkey do” instead of incorporating the knowledge. I looked it up and found that using img after a selector targets any img file used in that class and applies whatever styling one specifies to the image.

In my defense, I was trying to avoid using width and height but didn’t know of this exception. Are there others?

To view images in codepen you will need to use the absolute url to a location on the web assuming its an https location. (For codepen pro members (that’s a paid account not the free one) you can upload your images to an assets folder and then reference them from there.)

<img src="https://picsum.photos/id/1016/500/400" alt="page 1" class="scrapbook-right">

/id/1016/500/400

1016 = the image id reference
500 = image width
400 = image height

You can find a list of images on the site to use as placeholders.

No you will never ever need to do that :slight_smile: You just have to give the image a 100% width (and height:auto) to fill the available space as already mentioned.

object-fit is used on an image tag when you want to stretch and image in width and height to fill an element that is not the same aspect ratio as the image. If you use the value cover then the image has its width and height increased uniformly until the image covers the whole area. This means that unless the image is the same aspect ratio as the space you want to fill then width and height are increased until all the area is covered and then the overflow of the image is cropped. Usually this would mean putting height:100% and width:100% on the image assuming that the available height is computable.

If you use object-fit:contain on an image then the above scenario is the same except that if height or width reach the boundary of the element the expansion is stopped so that the whole original image is still visible. This means it will not fill all the space unless that space just happened to be the same aspect ratio as the image.

For your use case you don’t need any of that unless you wanted the image to match the height of a column or similar but that would be a little silly.:slight_smile: (Note in your examples you kept using object-fit on a div and that has no effect at all because a div is not an image.)

1 Like