External link inside flex item


#1

Note: this thread is related to Header layout

I am trying to build the view page where visitors would see screenshots of website mockups. Here I plan to add an external link to potential project website. I know its probably more a question of design nature than of HTML/CSS however I just wanted to know your opinion where would it be more semantically correct to add that link. Currently I put it in two places just to see how it would look: title attribute and at the bottom left of screenshot. If I keep the link only at the bottom of screenshot I would need to add some extra padding to second and third img just to keep even distance between screenshots

<div><a href=""><img src="images/thumb.png" alt="" 
width="600" height="425" title="www.google.com"></a>
<a href="" class="project-link">www.project.com</a></div>

Here’s an updated link http://buildandtest.atspace.cc/view.html


#2

The standard practice for an image that is a link is to nest the image in the anchor, as you have done. If you want some extra text giving more detail that the image is a link then you can just nest a span in the anchor too. There’s no need for duplicate anchors pointing to the same link.

Then you would just absolute position that span where you want it. The parent will need position:relative; to become the containing block.

    <div>
      <a href="#">
        <img src="images/thumb.png" alt="" width="600" height="425" title="www.project.com">
        <span>www.project.com</span>
      </a>
    </div>
.view div {
  margin: 0 0 3em;
  position: relative;
}
.view img {
  display:block;
}
.view span {
  position: absolute;
  bottom:10px; left:17px;
  padding:4px;
  background:rgba(255, 255, 255, .6);
  border-radius:4px;
}

view-page.html (3.1 KB)


#3

and if I want to put the span with link text below the screenshot I can use negative value like…?

.view span {
  position: absolute;
  bottom: -10px;

also since I want those screenshots just stack one on top of each other and occupy the whole container width
I guess I will need to keep this rule .view > div {flex-basis: 100%;} ?

also the following rule added bottom margin to the last img which increased the distance between the last img and social icons in the footer. since i was looking to keep same distance between them as on first page (work) I guess I need to target only three img from the top with bottom margin and exclude the last img ?

.view div {
  position: relative;
  margin: 0 0 3em;

#4

If you want the text below the image you can just set the span to display:block; and it will drop below the image on it’s own. Then you can remove all the positioning rules that were used.

Yes

Yes, you can remove the bottom margin from the :last-child
Or you could do top margins and remove margin from the :first-child

Now you can also use the <figcaption> with the <figure> element if your intending on doing image captions. Instead of using the spans.


#5

I did that but since display: block by default makes span expand to the whole width of container, the whole area on the right also becomes clickable (image attached). is it possible to make only the link itself clickable on hover?


#6

Yes, there is.

But first let me explain a couple of things. An <img> and a <span> are inline elements by default. The reason I set the image to display:block is so you didn’t have to contend with any whitespace (text descenders) below it. The other way is to set it to vertical-align:bottom; By setting it to block you are free to use margins if needed.

Likewise for the span, if you go ahead and get it in a block display you don’t have to deal with the default vertical-align:baseline; causing space at the bottom. You can also use margins if needed.

What you are looking for now is a shrink to fit block. That could be done with display:table; or display:inline-block; or a float and some others.

In this case, as far as I can see with your plans for the page, display:table should work fine for you.

.view span {
  display: table;
  padding: 4px;
  background: inherit; /*or whatever you need, no need for opacity now*/
  border-radius: 4px;
}

You are wanting the image to be a link too right?

If not then move it out of the anchor and then use the anchor below the image instead of the span.


EDIT:

Hang on, that's not going to work. That space will still be clickable because it is expanding the anchor.

Let me see what other options may be had :slightly_smiling_face:


#7

Didn’t know about those. I just googled it. Good to know

Correct.


#8

I just commented out display:block and padding and it removed that clickable area…

.view span {
  /* display: block;
  padding: 0.5em 0; */

#9

Are you sure it didn’t just shrink your red outline. Theoretically that span should still be expanding the anchor. Go back and hover in that white area to the right.

You let it go back to it’s default of display:inline; which shrinks to fit too.

I’ve got another solution too.


#10

No. The clickable area on the right is gone, however, it added some extra space between bottom of first and top of second image…:thinking:
I’ve updated the test link (please see post #1 in this thread).


#11

That’s because the anchor is still at it’s default of inline too. The inline formatting model is kinda of complex. In short the anchors box is shaped like the image and the span. It’s not a square box like a block would be. In that case my first suggestion would have worked but I would not use it with the anchor as display:inline;.

I would set the anchor as a block too and go back to a absolute positioned span at the bottom.

I think something like this is what your after…
Now just the image and span are clickable

<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Test Page</title>
<style>
.view {
  display:flex;
  flex-flow: column;
  align-items:center;
  max-width:900px;
  margin:auto;
  border: 1px solid;
}
.view div {
  box-sizing:border-box;
  max-width:620px; /*image size + 10px side paddings*/
  margin: 0 0 3em;
  position: relative;
  padding:0 10px 2.25em 10px;/* 2.25em space for the span*/
  outline:1px solid red;
}
.view a {
  display:block;
}
.view img {
  display:block;
  width:100%;
  height:auto;
  margin:auto;
  background:lime;
}
.view span {
  position: absolute;
  bottom: 0;
  left: 10px;
  font-size: 1rem;
  padding: .25rem;
  background: #eee ;
  border-radius:4px;
}
</style>

</head>
<body>

<div class="view">
  <div>
    <a href="#">
      <img src="https://via.placeholder.com/600x425" alt="" width="600" height="425" title="www.project.com">
      <span>www.project.com</span>
    </a>
  </div>
  <div>
    <a href="#">
      <img src="https://via.placeholder.com/600x425" alt="" width="600" height="425" title="www.project.com">
      <span>www.project.com</span>
    </a>
  </div>
  <div>
    <a href="#">
      <img src="https://via.placeholder.com/600x425" alt="" width="600" height="425" title="www.project.com">
      <span>www.project.com</span>
    </a>
  </div>
</div>

</body>
</html>




#12

just to clarify flex-flow is a short hand for flex-direction and flex-wrap. I looked it up further it looks like it is possible to use it without flex-wrap part…so flex-flow: column; is a valid declaration. my understanding we can also use just flex-direction: column here as well?


#13

Very good, glad to see you doing some research. :slightly_smiling_face:
Yes it is valid. When the flex-wrap value is omitted it is set to the default value.

Initial value as each of the properties of the shorthand:

Yes you can. I prefer to use shorthand so I can make adjustments to one or both properties later in a media query if I need to.

Here’s some good reading for you on that. It’s an old article but the specs haven’t changed much (if any) on inline formatting. Don’t get too involved in it, but it will be good for you to see that it is more complex than most people are aware of.
Inline formatting model

It’s just not a good idea to rely on inline format for laying out blocks in your page.
In fact, the display:flex on the parent <div class="view"> wasn’t really doing anything but stacking your divs as blocks, which is how divs layout on their own anyway.

Anytime you use an anchor for any type of box formatting it’s normally best to go ahead and set it as display:block; such as with what your doing or in the case of links in a navbar. If it is just a link within a string of text then yes it would stay at it’s default of inline.

Here is an example of what was going on when your anchor was left to it’s default of inline. Why it was working, and the other strangeness that was going on with it. You’ll see how the box breaks and wraps to a new line but only extends as far as it’s content. Perfect for text but not for page layout.
inline

<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Inline Box</title>
<style>

div {
  max-width:600px;
  margin:auto;
  border:1px solid;
  padding:10px;
  box-sizing: border-box;
}
div * {box-sizing: inherit;}

a {
  display: inline; /*default*/
  border: 2px dashed red;
  padding: 4px;
  text-decoration: none;
}
img, span {
  display:inline; /*default*/
  vertical-align:baseline; /*default*/
  line-height:1.2;
}
img {
  width:100%;
  max-width:400px;
  height:auto;
}
a span {
  padding:5px;
  background:yellow;
}
hr {
  margin:20px 0;
}
h1 {text-align:center}
</style>

</head>
<body>
<h1>Inline Anchor Box</h1>
<div>
  <a href="#">
    <img src="https://via.placeholder.com/400x225" alt="" width="400" height="225" title="www.project.com">
    <span>www.project.com</span>
  </a>
  <hr>
  <span style="border: 1px solid red">
    Lorem ipsum dolor sit amet consectetuer in faucibus malesuada Vivamus nunc.
    Cursus id tempus enim semper ante congue Vestibulum Nam pretium lacinia.
  </span>
</div>

</body>
</html>

#14

Thanks for the link. I knew it is more complex than block formatting context (BFC). My plan is after I finish this website to go back to some of Eric Meyer books I have and try to go through those concepts again.

I understand. But we also have main { display: flex;}…

Just as experiment I commented out the whole .view and added flex-basis: 100%; to .view div commenting out max-width: 620px; My intent was on view.html page to have those screen shots stack on top of each other at the same container width as index.html. I’ve updated the test link (please see post #1 in this thread). If it can be done without my changes please let me know.

I can’t figure out this one. Even though I removed bottom margin from last image with .view div:last-child the distance between the last image and the social icons is more than on index.html :thinking:


#15

There is also bottom padding on that element if you want to collapse all the space.

e.g.

.view div:last-child{padding-bottom:0}


#16

As Paul pointed out it’s the bottom padding on the .view divs. That padding was put there for the AP’d spans but you only have a span on the first div at this point. When you get your span in the last child div the padding will be needed.

Regardless of how the spans are styled they are going to take up X amount of space below the image. I absolute positioned them because you didn’t want the space to the right being clickable. That’s what would happen if the spans were display:block as it would expand the entire anchor (when the anchor is set to block, already explained).

You also have a 3em top margin on your footer ul.

If you find yourself needing page specific styling you can always add a class to the body element and style your desired target from there with a new descendant selector.

Your page is still a mixture of display table and flex. Your main wrapper div is still set to display:table. The header and main is now flex but the footer is still a table-row. I would go ahead and use flex for all.
I didn’t completely read your other thread but I see that Paul did mention using flex for the header. That’s where we wound up at anyway.

Your there now, embrace it :slightly_smiling_face:


#17

That’s fine, it’s just a different way of saying the same thing. It may keep things easier for you by not changing the flex-direction on <main class="view>


#18

you mean keep it like this…?

.view {
    flex-flow: column;
 }

.view div {
  position: relative;
  margin: 0 0 3em;
  padding: 0 7px 1.85em /* 1.85em space for the span*/
}

#19

I agree. Let me try…


#20

No, I meant keep it the way you had it, flex-flow: row wrap; along with flex-basis:100%;
I’m the one that changed it to column.

I don’t think it matters though since your .view class is only used on that page where the blocks fill the entire width.

Whichever your comfortable with.