Generally, a CNN layer may be used for images of any size. The number of weights in the CNN layer does not depend on the image size but on the number and shapes of kernels. So, for instance:
Conv2D(16, (3, 3), padding="same",input_shape=(None, None, 3))
has always 16(kernels) * 3 * 3 * 3(channels) + 16(biases) = 448 weights.
The only problem is that a head of the network is typically a set of Dense layers that have a fixed number of inputs. So, if you just Flatten your network between Conv2D and Dense layers, the size of images must be fixed. But if you put for instance tf.keras.layers.GlobalAveragePooling2D layer, the size of images may be variable as this layer produces output that depends only on the number of kernels and not on the size of images.
If you use versions with heads (include_top parameter):
base_model = tf.keras.applications.VGG16(weights = 'imagenet', include_top = True)
or
base_model = tf.keras.applications.MobileNet(weights = 'imagenet', include_top = True)
you may check with base_model.summary() that they expect images with size (224,224,3).
But if you add include_top=False like here:
base_model = tf.keras.applications.VGG16(weights = 'imagenet', include_top = False)
the expected input_shape of the image is (None, None, 3). Such a network for an image of size (W, H, 3) produces an output of size (W/S, H/S, K) where K is the number of kernels in the last layer and S is the shrinkage factor of the specific network. For instance for VGG16 network S=32 and K=512, so for image of size (224,224,3) the output size is (7,7,512) and for image of size (512,512,3) the output is (16,16,512). Such an output is sometimes called the 'patch'.
So, if you want to build the network that uses some pretrained network and classifies images of any size, you may build it like this:
base_model = tf.keras.applications.ResNet50(weights = 'imagenet', include_top = False)
x = base_model.output
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dense(512, activation = 'relu')(x)
...
last_layer = tf.keras.layers.Dense(num_classes, activation = 'softmax')(x)
model = tf.keras.models.Model(inputs = base_model.input, outputs = last_layer)
Such a model may be fed with images of any size and produces the probalitity vector for num_classes classes. Of course during training you must use images of the same size in one batch, but then you may use any image.